Руководство оператора коннектора AD Крепость#
Коннектор предназначен для взаимодействия с API СУУПТ (АС Система учета и управления ПУЗ и ТУЗ) для управления учетными записями в AD Крепость.
Сценарии использования#
Коннектор предоставляет следующие операции. Для асинхронных операций (все, кроме SEARCH) идентификатор типа операции добавялется к name проекции в IDM, для сохранения информации об обрабатываемых операциях.
Создание учетной записи -
CREATE.Обновление учетной записи -
UPDATE.Поиск учетных записей -
SEARCH.Проверка состояния соединения -
TEST.Включение/выключение учетной записи -
DISABLE.Разблокировка/Сброс пароля -
UNLOCK.
Порядок обработки асинхронных операций следующий:
Вызывается соответствующий метод в
FortressApiClient(например,disableFortressUser,unlockUser).API возвращает документ (request) с ID и статусом в формате
{payload: {id, status}}.ID документа сохраняется в
NameWrapperвместе с типом операции.Учетная запись возвращается с пометкой о выполняющейся операции.
При последующем поиске статус документа проверяется через
GET /documents/status/{id}.Если операция завершена успешно, учетная запись доступна для новых операций.
Операции считаются выполняющимися, когда документ имеет статус in_progress.
Каждая асинхронная операция создает документ в АС СУУПТ с уникальным ID, который сохраняется в атрибуте имени name проекции IDM в формате:
<имя_УЗ_в_СУУПТ>#<ОПЕРАЦИЯ>_<ID_ДОКУМЕНТА>&<ОПЕРАЦИЯ>_<ID_ДОКУМЕНТА>&<ОПЕРАЦИЯ>...
Коннектор использует следующие HTTP-методы для взаимодействия с СУУПТ:
GET /health- проверка состояния сервиса.Например,
/health GET, headers: {Accept=[application/json]}, body: <empty>.POST /msad/fortress/user- создание/обновление учетной записи.Например,
/msad/fortress/user POST, headers: {x-auth-token=[***], Content-Type=[application/json]}, body: ${"passwordNeverExpires":false,"sAMAccountName":"12341234","initials":"П.О.","displayName":"Барон Пауло Олигархович","givenName":"Пауло","description":"Учетная запись пользователя, Барон Пауло Олигархович","distinguishedName":"CN=12341234,OU=Users,OU=SMTH,OU=Fort,OU=MyBusiness,DC=IDM,DC=LOCAL","employeeId":"000123123123","co":"RUSSIAN FEDERATION","title":"Дежурный","passwordRequired":true,"unicodePwd":"*****","middleName":"Олигархович","sn":"Барон","department":"“Отдел”_‘03’_1","userPrincipalName":"12341234@smartbio.sbrf.ru"}.POST /msad/fortress/user/search- поиск учетной записи.Например,
/msad/fortress/user/search POST, headers: {x-auth-token=[***], Content-Type=[application/json]}, body: ${"sAMAccountName":"12341234"}.POST /msad/fortress/user/disable- включение/выключение учетной записи.Например,
/msad/fortress/user/disable POST, headers: {x-auth-token=[***], Content-Type=[application/json]}, body: ${"sAMAccountName":"12341234","enable":false}.POST /msad/fortress/user/unlock- разблокировка/сброс пароля учетной записи.Например,
/msad/fortress/user/unlock POST, headers: {x-auth-token=[***], Content-Type=[application/json]}, body: ${"password":"*****","sAMAccountName":"12341234"}.GET /documents/status/{id}- получение статуса документа по ID.Например,
/documents/status/2 GET, headers: {Accept=[application/json], x-auth-token=[***]}, body: <empty>.
Формат ответов от API СУУПТ#
Все POST-запросы, создающие операции (user, user/disable, user/unlock), возвращают ответ в формате:
{
"payload": {
"id": "<documentId>",
"status": "<status>"
}
}
Для GET-запроса статуса документа возвращается аналогичный формат:
{
"payload": {
"id": "<documentId>",
"status": "in_progress|success|failed"
}
}
Для отсутствующих ресурсов (404) возвращается null при allowNotFoundDocument=true или allowNotFoundAccount=true.
Если возвращается некорректный ответ (то есть не соответствующий форматам выше), то возможны три реакции:
Если в ответе присутствует элемент
payloadи в нем вернулся статусin_progress- IDM будет продолжать ожидание завершения операции на стороне СУУПТ.Если в ответе присутствует элемент
payloadи в нем вернулся статус, отличный отin_progress- он будет считаться конечным и будет помещен в атрибут shadowdocument.status. Если статус не соответствует статусам, обрабатываемым коннектором (in_progress|success|failed) - дальнейшая обработка выполняться не будет, операция будет считаться завершенной, изменений в УЗ или карточке не будет.Если в ответе присутствует элемент
payloadи в нем не вернулся статус - этот ответ будет проигнорирован, статус будет указан какnull.Если в ответе отсутствует элемент
payload- IDM вернет соответствующую ошибку (payload in document response not found!).
Если происходит сетевая ошибка - в shadow отмечается pendingOperation (механизм IDM, не значение атрибута), и, в зависимости от политики повторов в системной конфигурции, при пересчете (recompute) данная операция будет выполнена повторно. Если после указанного в политике количества повторов операция была не выполнена успешно - она отмечается как failed и больше не обрабатывается.
Операция CREATE#
В процессе выполнения операции выполняется поиск УЗ. Если запись отсутствует, то будет выполнено создание новой УЗ. Если УЗ найдена по имени, то будет выброшено исключение ObjectAlreadyExists.
Из-за особенности системы СУУПТ, запрос на создание выполняется асинхронно. Для того, чтобы коннектор корректно мог продолжать работу в методе SEARCH, в имя объекта (из метода CREATE можно вернуть только объект, который содержит уникальный идентификатор для shadow UID + NAME) добавляется информация о текущем запросе на создание УЗ - documentId. Формат имени - {Name}#{ТИП_ЗАПРОСА}_{documentId} -> testUser#CREATE_1.
Также, при успешном завершении операции CREATE, после создания УЗ выполняется дополнительный вызов операции UNLOCK к созданной УЗ для установки транспортного пароля.
Операция SEARCH#
Данная операция позволяет выполнить поиск УЗ, и, на основе полученных данных от СУУПТ, создать connectorObject (shadow). Поиск может выполняться с 2 фильтрами:
Фильтр по
UID + NAME- IDM использует данный фильтр, если корректно завершилась операцияCREATE. Если вNAMEбудет найдена информация об операцииCREATE/UPDATE, то также вconnectorObjectбудут добавлены атрибутыdocument.idиdocument.status, которые будут содержать информацию об операции.Для операции
CREATEбудет возвращатьсяconnectorObjectв котором будет только информацию о запросе, а для операцииUPDATEбудет возвращатьсяconnectorObjectс текущими атрибутами + атрибутыdocument.id,document.status.Если на момент выполнения операции (
CREATE/UPDATE), запрос имеет завершенный статус (success/error), то из имениconnectorObjectбудет удален постфикс (CREATE_1/UPDATE_2) с информацией о запросе.Если операция
CREATEзавершилась, то также вconnectorObjectдобавляется атрибутactions = FORCE_CHANGE_PASSWORD_AFTER_CREATE, который позволяет при пересчете выполнить установку транспортного пароля для УЗ.Фильтр по
NAME- IDM использует данный фильтр, если операцияCREATEзавершилась с ошибкойObjectAlreadyExists. Выполняется поиск УЗ и создаетсяconnectorObject(shadow) на основе полученных данных из СУУПТ.
Для обработки запросов в IDM добавлена задача, которая выполняет поиск shadow у которых в имени есть информация о каком-либо запросе и выполняется пересчет для владельца данного shadow с использованием функционала fastAssignment.
Операция UPDATE#
Данная операция позволяет обработать изменения атрибутов со стороны IDM и выполнить определенные действия на основе тех атрибутов, которые пришли на изменение.
Включение/выключение (операционное действие) - если в дельте изменений пришли изменения по атрибуту, который отвечают за статус УЗ (настраивается в ресурсе и конфигурации коннектора), то будет выполнена включение/выключение УЗ в зависимости от значение на которые выполняется изменение.
Раблокировка/сброс пароля (операционное действие) - если в дельте изменений пришли изменения по операционным атрибутам IDM:
PASSWORD- атрибут отвечает за значение пароля, который изменяется в shadow. Может вычисляться в ресурсе, когда в shadow был установлен атрибутactions = FORCE_CHANGE_PASSWORD_AFTER_CREATE.LOCK_OUT- атрибут отвечает за разблокировку УЗ. Если в дельте атрибут изменяется на значениеfalse, то будет выполнена разблокировка УЗ.
Обновление - если в процессе выполнения не было выполнено операционных действий, а именно в дельте изменений отсутствуют атрибуты для операционных действий, то будет выполнено обновление УЗ на основе атрибутов из дельты.
Для данного ресурса установлен параметр
update/attributeContentRequirement, это означает что в дельту передаются все атрибуты, которые вычисляются в ресурсе. Это позволяет при выполнении операционных действиях использовать атрибуты (например, при включении УЗ необходимо передавать атрибутaccountExpires, который заполняется на основе даты увольнения).
При выполнении операционных действий пропускается обновление УЗ, чтобы не создавались лишние требования на обновление, так как в дельте присутствуют все атрибуты (из-за update/attributeContentRequirement).
Операции UNLOCK и DISABLE#
Данные операции являются подвидом операции UPDATE (а именно, выполняются в рамках этой операции).
При этом, в атрибуты REST-запроса передаются соответствующие значения, например lockoutStatus = true/false для блокировки или разблокировки УЗ.
В случае DISABLE коннектор проверяет наличие у учетной карточки первичной роли AD Крепость, и если она изымается (или выполняется disable) - в рамках операции UPDATE вызывается соответствующий эндпоинт.
Структура маппингов FORTRESS#
Объектный тип: kind = account, intent = default, objectClass = ri:AccountObjectClass (→ FortressAccount). Все маппинги — outbound (из IDM в ресурс).
№ |
Атрибут ресурса |
Display name |
Источник (source) |
Сила |
Matching rule |
Источник значения (выражение) |
|---|---|---|---|---|---|---|
1 |
|
User Principal Name |
|
weak |
— |
|
2 |
|
— |
|
weak |
— |
прямое копирование |
3 |
|
— |
|
strong |
|
|
4 |
|
Title |
— |
strong |
— |
|
5 |
|
— |
— |
— |
— |
— (не маппится) |
6 |
|
— |
— |
— |
— |
— (не маппится) |
7 |
|
— |
— |
— |
— |
— (не маппится) |
8 |
|
Country or region |
— |
weak |
— |
константа |
9 |
|
EmployeeID |
— |
strong |
— |
|
10 |
|
First name |
— |
strong |
— |
|
11 |
|
Last name |
— |
strong |
— |
|
12 |
|
Other name |
— |
strong |
— |
|
13 |
|
Initial |
— |
strong |
— |
|
14 |
|
Display Name |
— |
weak |
— |
|
15 |
|
Description |
— |
strong |
— |
|
16 |
|
Company name |
— |
strong |
— |
|
17 |
|
Department name |
— |
strong |
— |
|
18 |
|
— |
— |
— |
— |
смотрите раздел Credentials / password |
19 |
|
— |
|
strong |
— |
смотрите раздел Маппинг активации (activation) |
Скрипты выражений#
#1 ri:userPrincipalName (domain = smartbio.sbrf.ru):
return adMappingsLib.execute("userPrincipalName",
["nickName": nickName, "domain": "smartbio.sbrf.ru"])
#2 ri:sAMAccountName: прямое значение из source → $focus/nickName (выражения нет).
#3 ri:distinguishedName (mr:stringIgnoreCase, домен OU=Fortress,OU=Sberbank,DC=IDM,DC=LOCAL):
return adMappingsLib.execute("distinguishedNameFosByCos",
["user" : user,
"domain" : "OU=Fortress,OU=Sberbank,DC=IDM,DC=LOCAL",
"method" : "fosDefaultTest",
"resource" : resource,
"nickName" : nickName,
"projection": projection])
#4 ri:title:
return adMappingsLib.execute("title", ["user": user])
#8 ri:co: константа через <expression><value>RUSSIAN FEDERATION</value></expression>.
#9–#17 — единый паттерн, подставляемый атрибут:
return adMappingsLib.execute("<атрибут>", ["user": user])
где <атрибут> = employeeID, givenName, sn, middleName, initials, displayName, description, company, department.
Маппинг активации (activation)#
administrativeStatus (outbound, сила strong):
Источник:
name = admStatus,path = activation/administrativeStatusВыражение:
import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType;
if (!assigned) {
return ActivationStatusType.DISABLED
}
boolean result = mapLib.execute("isAccountActiveOnlyContractStatus",
["user": user, "admStatus": admStatus]);
return result ? ActivationStatusType.ENABLED : ActivationStatusType.DISABLED
validTo — в текущей конфигурации закомментирован. Предназначался для вычисления expirationDate для запроса /msad/fortress/user/disable; срабатывал только при изменении administrativeStatus.
existence (outbound) — условие существования объекта:
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
return mapLib.execute("checkResourceFocus",
["focus": focus, "targetClass": UserType.class]);
Credentials / password#
password (outbound, сила strong) — транспортный пароль. Заполняется только после создания УЗ (см. условие).
Условие срабатывания (condition):
if (projection == null || projection.getOid() == null) {
return false
}
Collection actions = basic.getAttributeValues(projection, "actions")
log.debug("Projection actions: {}", actions)
return actions != null && actions.contains("FORCE_CHANGE_PASSWORD_AFTER_CREATE")
Выражение (expression):
def newPwdBytes = mapLib.execute("generateADPassword", Collections.emptyMap())
return new String(newPwdBytes)
Корреляция (correlation)#
Сопоставление shadow-объекта с владельцем (ownerFilter) по полю nickName:
String name = basic.getAttributeValue(projection, "sAMAccountName")
assert name != null : "Correlation attribute not found"
def args = name.split("#")
return args[0]
Значение
sAMAccountNameможет иметь формат<nickName>#…; для корреляции используется часть до#.
Задача пересчета пользователей#
Задача FORTRESS Card recompute
Задача выполняет поиск shadow, у которых в имени присутствует постфикс #CREATE/#UPDATE.
Это означает, что для данной УЗ выполняется какая-то операция на стороне СУУПТ, и для данной УЗ необходимо выполнять пересчет (выполняется для пользователя через fastAssignment), чтобы подтянуть актуальные данные.
Когда операция для пользователя завершена, из имени shadow удаляется постфикс #CREATE/#UPDATE (это выполняется на стороне коннектора).
Задача реконсиляции пользователей#
Задача FORTRESS Reconciliation выполняет реконсиляцию shadow, связанных с ресурсом AD Крепость. Задача получает изменения, внесенные на стороне СУУПТ. При этом обновляются атрибуты в проекциях, никаких перерасчетов не выполняется.
Просмотр событий аудита#
Для отслеживания выполнения операций используется UI IDM. Чтобы найти нужную запись, следуйте инструкции:
В IDM перейдите на вкладку Аудит.
Добавьте фильтр по ресурсу, указав в поле Ресурс имя ресурса FORTRESS.
Нажмите кнопку Обновить.
В списке отобразятся все события конкретного ресурса. Для поиска операций с конкретной УЗ - добавьте в фильтр в поле Целевой объект имя требуемой проекции (не указывая постфикс операции).
Если требуется отобразить только конкретные операции - можно указать в поле Целевой объект только постфикс операции (например,
CREATE). Тогда будут отображены все события аудита, относящиеся к указанному ресурсу FORTRESS и имеющие в имени проекции указанный постфикс. Обратите внимание, данная фильтрация смотрит только на текущее имя проекции, а не на имя в записи аудита.
Просмотр логов#
Все действия, производимые компонентом IDMX (компонент idmx-engine) логируются, логи записываются в файлы на сервере. IDMX создает файлы журнала в директории /app/idmx-engine/var/log.
Основной файл для работы - idm-engine.log. В него вносятся все логи работы IDMX.
В случае, если нужно получить логи интеграции с AD, то необходимо настроить категорию коннектора Fortress.
Настроить категорию можно вручную согласно инструкции ниже.
Перейдите в UI IDM > Система > Логирование.
Перейдите в пункт Class loggers.
Нажмите кнопку + и добавьте категорию
ru.sbertech.idm.connector.fortress, выставив необходимый уровень логирования. В средах разработки и тестирования рекомендуется использование уровняDEBUG. В PROD-среде рекомендуется использование уровня не нижеINFO.
Дополнительные логгеры для более детальной информации:
ru.sbertech.idm.connector.fortress.FortressConnector- логирование операций коннектора.ru.sbertech.idm.connector.fortress.client.FortressApiClient- логирование вызовов API СУУПТ.