Разработка восстановления доступа | Avanpost FAM/MFA+

10.9. Разработка скрипта восстановления доступа

Общие сведения

Функциональность управления сценариями восстановления доступа в Avanpost FAM позволяет администратору настраивать процессы восстановления доступа пользователей к учетным записям при утере или компрометации учетных данных. Скрипт восстановления доступа позволяет настроить гибкие сценарии восстановления доступа пользователей к учётной записи с учётом различных условий: устройства, групповой принадлежности, наличия настроенных факторов аутентификации и внешних проверок. Данная функциональность решает следующие задачи:

  • Настройка сценариев восстановления доступа с использованием скриптов.
  • Определение последовательности действий, которые должен выполнить пользователь при восстановлении доступа.
  • Интеграция с внешними системами посредством HTTP/HTTPS-запросов для обработки событий восстановления доступа.

Текущая инструкция описывает методику разработки скрипта аутентификации на языке JavaScript.

Предполагается, что разработчик сценария скрипта восстановления доступа обладает следующими компетенциями:

  • владение языком программирования ECMAScript 5.1 или JavaScript;
  • понимание механизма многофакторной аутентификации, реализуемого Avanpost FAM, и способов его диагностики.

Для создания нового сценария восстановления доступа необходимо:

  1. Перейти в раздел «Редактор скриптов» режима «Сервис» (также имеется возможность перейти из раздела «Системные настройки» режима «Сервис»).
  2. Нажать кнопку «Добавить».
  3. Заполнить параметры сценария:
    ПараметрЗначение
    Имя

    Наименование сценария, отображаемое в административной консоли.

    ТипТип сценария. Для скрипта восстановления доступа: Account Recovery.
    СкриптЗадать скрипт, определяющий логику восстановления доступа.

Выбор настроенного скрипта восстановления доступа выполняется в разделе «Системные настройки» режима «Сервис». Для этого требуется:

  1. Перейти в подраздел «Настройки восстановления доступа к аккаунтам» в разделе «Системные настройки».
  2. Для параметра «Механизм восстановления пароля» выбрать значение «Скриптовый»
  3. В разделе «Выбранный скрипт» выбрать настроенный скрипт из выпадающего списка.
  4. Нажать "Сохранить" для сохранения или "Отмена", чтобы не вносить изменения. 

Сценарии использования

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

  1. Порядок выполнения: проверки, прерывающие процесс (context.StopProcess), должны располагаться перед логикой добавления шагов (context.AddStep).
  2. Единственная точка выхода: скрипт должен завершаться либо вызовом context.AddStep() (успешное добавление шага), либо context.StopProcess() (блокировка процесса), либо return после одного из этих вызовов.
  3. Повторное использование переменных: объекты контекста (user, req, session) следует получать один раз в начале скрипта и повторно использовать в дальнейшей логике скрипта.
  4. Обработка внешних запросов: вызовы context.Send() рекомендуется выполнять в начале сценария, сразу после идентификации пользователя.

Проверка статуса устройства

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


// Получение контекста запроса
var req = context.GetRequest();

// Проверка: устройство существует в системе и его статус не "Active"
if (req.Device != null && req.Device.ExistsInTheSystem && req.Device.Status != 'Active') {
    // Прерывание процесса с выводом сообщения пользователю
    context.StopProcess("Устройство заблокировано, обратитесь к администратору!");
    return;
}

// Если проверка пройдена — процесс продолжается
// (далее следует логика добавления шагов аутентификации)

Блокировка восстановления для привилегированных учетных записей


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

// Получение объекта пользователя
var user = context.GetUser();

// Проверка имени пользователя на совпадение с привилегированными учетными записями
// Допускается использование строгого сравнения (===) или регулярных выражений
if (user.Name === "superuser" || user.Name === "superadmin") {
    context.StopProcess("Для вашей учетной записи самостоятельное восстановление пароля запрещено, обратитесь в службу безопасности!");
    return;
}

// Если пользователь не входит в список исключений — процесс продолжается

Упрощенный сценарий для пользователей из внутренней сети

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

// Получение объектов пользователя и запроса
var user = context.GetUser();
var req = context.GetRequest();

// Проверка: пользователь имеет атрибут IsVIP и подключается из доверенной подсети
// Метод InSubNet поддерживает запись в формате CIDR
if (context.InSubNet(req.IPAddress, '::1/128') && user.Attributes["IsVIP"] === 'true') {
    // Добавление шага с выбором из двух упрощенных факторов
    context.AddStep(
        [
            { factor: "telegram" },   // Push-уведомление в Telegram
            { factor: "qrsignin" }    // Вход по сканированию QR-кода
        ]
    );
    // Завершение скрипта — шаг добавлен, процесс передан пользователю
    return;
}

// Если условия не выполнены — скрипт не добавляет шаг.

Интеграция с внешней системой

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

// Выполнение синхронного HTTP-запроса к внешней системе
// Важно: внешние запросы рекомендуется выполнять в начале сценария, сразу после идентификации
var hrResponse = context.Send({
    method: "GET",
    url: "https://httpbin.org/ip",
    headers: {
        "Authorization": "Bearer XXXTOKEN",
        "Accept": "application/json"
    }
});

// Обработка успешного ответа (код статуса 200)
if (hrResponse.statusCode === 200) {
    // Парсинг JSON-ответа
    var data = JSON.parse(hrResponse.body);
    
    // Проверка: совпадает ли источник запроса с ожидаемым значением
    if (data.origin === "176.193.198.27") {
        // Сохранение результатов проверки в объект сессии для дальнейшего использования
        var session = context.GetSession();
        session.SetValue("hr_my_ip", data.origin);
        session.SetValue("hr_verification_ok", "true");
        session.SetValue("hr_check_timestamp", new Date().toISOString());
        // Проверка пройдена — процесс продолжается
    } else {
        // Сотрудник не найден в активном штате — блокировка восстановления
        context.StopProcess("Сотрудник не числится в активном штате. Восстановление запрещено, обратитесь к администратору!");
        return;
    }
}

// Обработка ошибок внешней системы
if (hrResponse.statusCode !== 200) {
    context.StopProcess("Ошибка проверки в HR-системе. Попробуйте позже.");
    return;
}

Проверка членства в группах для контроля доступа к восстановлению

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

// Получение объекта пользователя
var user = context.GetUser();

// Вариант 1: Проверка наличия пользователя в разрешающих группах
var hasRecoveryAccess = user.Groups.some(function(g) {
    return g.Name === 'RestorePasswordAvailable_Group1' || 
           g.Name === 'RestorePasswordAvailable_Group2';
});
if (!hasRecoveryAccess) {
    context.StopProcess("Самостоятельное восстановление запрещено вашими групповыми политиками(1), обратитесь к администратору!");
    return;
}

// Вариант 2: Проверка отсутствия пользователя в запрещающих группах
// (может использоваться отдельно или в комбинации с Вариантом 1)
for (var i = 0; i < user.Groups.length; i++) {
    if (user.Groups[i].Name === 'Restore_Password_FORBIDDEN') {
        context.StopProcess("Самостоятельное восстановление запрещено вашими групповыми политиками(2), обратитесь к администратору!");
        return;
    }
}

// Если все проверки пройдены — процесс продолжается

Динамический выбор фактора аутентификации по приоритету

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

// Получение списка включенных аутентификаторов пользователя
var authenticators = context.GetEnabledAuthenticators();

// Определение приоритетов факторов (от наиболее безопасного к наименее)
// Порядок элементов в массиве определяет приоритет выбора
var priorityMap = [
    "hardware",      // Аппаратный токен
    "cert",          // Электронная подпись
    "authenticator", // Avanpost Authenticator (Push/TOTP)
    "totp",          // Программный TOTP
    "sms",           // SMS OTP
    "email"          // Email OTP
];

var selectedFactor = null;

// Поиск первого доступного фактора из списка приоритетов
for (var i = 0; i < priorityMap.length; i++) {
    var currentPriority = priorityMap[i];
    
    // Проверка: есть ли у пользователя включенный аутентификатор данного типа
    var hasAuth = authenticators.some(function(a) {
        return a.MethodFactor === currentPriority;
    });
    
    if (hasAuth) {
        selectedFactor = currentPriority;
        break; // Первый найденный приоритетный фактор — выбираем его
    }
}

// Добавление шага аутентификации с выбранным фактором
if (selectedFactor) {
    // Особая обработка для фактора "authenticator" (алиас "push")
    if (selectedFactor == "authenticator") {
        context.AddStep([{ factor: "push" }]);
    } else {
        context.AddStep([{ factor: selectedFactor }]);
    }
} else {
    // Ни один из приоритетных факторов не доступен — блокировка процесса
    context.StopProcess("Нет доступных аутентификаторов, обратитесь к администратору!");
    return;
}

Адаптация сценария на основе уровня риска

Скрипт добавляет дополнительный шаг аутентификации, если выбранный фактор имеет низкий уровень надежности, а уровень риска пользователя ниже заданного значения. Рекомендуется для динамического усиления сценариев восстановления в зависимости от контекста сессии и профиля риска пользователя.

// Получение уровня риска пользователя
var risk = context.GetUserRisk();

// Предположим, что на предыдущем шаге уже выбран фактор "sms"
var selectedFactor = "sms";

// Если выбран SMS и уровень риска ниже порога (39),
// добавляем второй фактор (telegram) для многофакторной проверки
if (selectedFactor == "sms" && risk < 39) {
    context.AddStep([{ factor: "telegram" }]);
}

// Примечание: данный фрагмент должен быть частью более крупного сценария,
// где selectedFactor определен на предыдущих шагах

Спецификация функций

Параметры и методы, используемые в скрипте восстановления доступа:

Параметр значение
context.GetUser()Возвращает объект пользователя с атрибутами и группами
context.GetRequest()Возвращает объект запроса (устройство, IP-адрес)
context.GetActiveUserSessions()Возвращает список активных сессий пользователя
context.GetSession()Возвращает объект текущей сессии для сохранения данных
context.GetEnabledAuthenticators()Возвращает список включённых аутентификаторов пользователя
context.GetUserRisk()Возвращает уровень риска (числовое значение)
context.AddStep([...])Добавляет шаг аутентификации с указанными факторами
context.StopProcess("message")Прерывает процесс восстановления с сообщением
context.Send({...})Выполняет HTTP-запрос к внешней системе
context.InSubNet(ip, subnet)Проверяет принадлежность IP-адреса к подсети

Обсуждение