Полное руководство по установке IDM Midpoint и подключению к MS AD

от автора

Подключение IDM Midpoint к Microsoft Active Directory (MS AD) стандартная и ключевая задача, однако практического руководства как это сделать от Evolveum( и не только) нет, постараюсь досконально описать как это делать!

I Установка Midpoint

Почти всё, что нужно делать, описано на страничке Evolveum: docs.evolveum.com/midpoint/install/bare-installation/distribution docs.evolveum.com/midpoint/reference/support-4.9/repository/native-postgresql/usage/ docs.evolveum.com/midpoint/install/bare-installation/systemd/

Беру Ubuntu 22.04.5 LTS со статическим IP 192.168.1.174

Далее консольные команды

sudo apt-get update && sudo apt-get upgrade

sudo apt install openjdk-21-jdk -y
Смотрим установленную версию

java -version

openjdk version «21.0.4» 2024-07-16

OpenJDK Runtime Environment (build 21.0.4+7-Ubuntu-1ubuntu222.04)

OpenJDK 64-Bit Server VM (build 21.0.4+7-Ubuntu-1ubuntu222.04, mixed mode, sharing)

sudo apt install -y postgresql

Смотрим установленную версию (нужно минимум 14)

pg_config --version

PostgreSQL 14.13 (Ubuntu 14.13-0ubuntu0.22.04.1)

vi /etc/postgresql/14/main/postgresql.conf

Добавляем

listen_addresses = '*' # this is necessary for pg_stat_statements extension shared_preload_libraries = 'pg_stat_statements'  # To log all queries, uncomment the lines below. # Monitor the free disk space afterwards, there is no automatic cleanup! #log_directory = 'pg_log' #log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' #log_statement = 'all' #logging_collector = on

vi /etc/postgresql/14/main/pg_hba.conf

Добавляем

# Allow connections from outside (with password) host    all             all             0.0.0.0/0            md5

Перезапускаем postgre

sudo systemctl restart postgresql

Смотрю доступные версии Midpoint docs.evolveum.com/midpoint/release/

Я взял 4.9 новейшую версию, и к концу статьи сильно жалел уже об этом… С одной стороны я хотел посмотреть что добавили нового и действительно добавили, но пока не понятно на кой, с другой стороны я надеялся, что все старые глюки исправили, но Evolveum добавил новый! Не фатальные для демонстрации, и даже полезные в плане познания, но как такое можно релизить!!! Всё ниже описанное точно также настраивается в версии 4.8.4-4.8.5.

cd /opt

wget https://evolveum.com/downloads/midpoint/4.9/midpoint-4.9-dist.tar.gz

tar -xvf midpoint-4.9-dist.tar.gz

mv ./midpoint-4.9 ./midpoint

Создаю базу и пользователя для Midpoint в postgresql

sudo -i -u postgres psql

CREATE USER midpoint WITH PASSWORD 'password_14968' LOGIN SUPERUSER;

CREATE DATABASE midpoint WITH OWNER = midpoint ENCODING = 'UTF8' TABLESPACE = pg_default LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8' CONNECTION LIMIT = -1;

/q

cd /opt/midpoint/doc/config/sql/native

psql -h localhost -d midpoint -U midpoint -f postgres.sql -f postgres-audit.sql -f postgres-quartz.sql

Странности с конфигом, но работает именно если так
rm /opt/midpoint/var/config.xml

cp /opt/midpoint/doc/config/config-native.xml /opt/midpoint/var/config.xml

vi /opt/midpoint/var/config.xml

меняем на свои данные до вида

        <repository>             <type>native</type>             <jdbcUrl>jdbc:postgresql://localhost:5432/midpoint</jdbcUrl>             <jdbcUsername>midpoint</jdbcUsername>             <jdbcPassword>password_14968</jdbcPassword>         </repository>

Первый запуск Midpoint

/opt/midpoint/bin/midpoint.sh start

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

grep "Administrator initial password" /opt/midpoint/var/log/midpoint.log

Заходим http://192.168.1.174:8080/midpoint/

С одной стороны убеждаемся, что заработало (если нет — смотрим, что пишет в /opt/midpoint/var/log/midpoint.log), а с другой тут нам надо сразу же отключить нормализацию данных, до того как появятся какие то данные, чтобы например в name можно было писать кириллицей.

В Repository objects > All objects открываем SystemConfiguration

Находим тэг

<internals>

и вставляем

 <polyStringNormalizer>   <className>PassThroughPolyStringNormalizer</className>   </polyStringNormalizer>

После перезапуска Midpoint

/opt/midpoint/bin/midpoint.sh stop

/opt/midpoint/bin/midpoint.sh start

Надо в Midpoint в About нажать Reindex Repository Object

Для запуска Midpoint при загрузке Ubuntu выполняем

sudo -i

/opt/midpoint/bin/midpoint.sh generate

Нам генерируют код, на основе midpoint.sh который нужно вставить в файл

vi /etc/systemd/system/midpoint.service

код

[Unit] Description=MidPoint Standalone Service  [Service] User=root WorkingDirectory=/opt/midpoint ExecStart="java" -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms2048M -Xmx4096M -Dpython.cachedir="/opt/midpoint/var/tmp" -Djavax.net.ssl.trustStore="/opt/midpoint/var/keystore.jceks" -Djavax.net.ssl.trustStoreType=jceks -Dmidpoint.home="/opt/midpoint/var" -jar "/opt/midpoint/lib/midpoint.jar" SuccessExitStatus=143  [Install] WantedBy=multi-user.target

и какие команды исполнить чтобы он срабатывал, выполняем

sudo systemctl daemon-reload

sudo systemctl enable midpoint

На загрузке Midpoint запоститься сам, а дальше чтобы его остановить запустить

sudo systemctl stop midpoint

sudo systemctl start midpoint

или

sudo systemctl restart midpoint

ОДНАКО: Через месяц после релиза обнаружилось, что новый AD коннектор в 4.9 не работает с MS AD. Evolveum винит Microsoft, я виню Evalveum потому что работу с AD они показывают на Open LDAP и говорят что в MS AD так же! ADLDAP connector LDAP error during search: operationsError: 00002120: SvcErr: DSID-03120496, problem 5012 (DIR_ERROR), data 592060?? (1) support.evolveum.com/projects/midpoint/work_packages/10207/activity

Скачиваем старый коннектор, которого уже нет в 4.9

cd /opt/midpoint/var/connid-connectors

wget https://nexus.evolveum.com/nexus/repository/releases/com/evolveum/polygon/connector-ldap/3.7.2/connector-ldap-3.7.2.jar

перестарутем Midpoint

sudo systemctl restart midpoint

II Подключение Midpoint к MS AD

Берем Windows Server 2019 (оригинальный бесплатно 180 дней) — установлены роли AD и Certification Authority

Midpoint должен подключаться по LDAPS поэтому настраиваем Windows Server 2019 по любой ссылке на слова Step by step guide to setup LDAPS on Windows Server

В результaте получим файл сертификата WindowsMSAD.cer, забрасываем его на сервер Midpoint и добавляем его в его keystore

sudo keytool -keystore /opt/midpoint/var/keystore.jceks -storetype jceks -storepass changeit -import -alias WindowsMSAD -trustcacerts -file ./WindowsMSAD.cer

sudo systemctl restart midpoint

На Windows Server 2019 создаём пользователя midpoint, добавляем его в группу Domain Admins

Настраиваем Resource в Midpoint

В Resource\New Resorce\From Scratch выбираем AdLdapConnector 3.7.2

Настраиваем по картинкам, имя Windows MS AD

Bind DN и password — для пользователя AD midpoint

Указываем Base context, можно только выбрать из того что даёт, можно поменять потом.

Тут выбираем что мы берём из AD, и вот это уже нельзя будет поменять

первые три рекомендует Midpoint

user

group

msDS-ManagedServiceAccount

взял еще OU буду из них строить ролевую модель

organizationalUnit

Ресурс готов, ресурс пустой, на нем можно понажимать Test connection — хорошо когда всё зелёное!

III Настройка привязки Midpoint к учёткам пользователей из MS AD

Наша схема работы с AD будет такой.

Пользователи в Midpoint появляются вручную или из ресурса, подключённого к кадровому источнику, которым может быть файл CSV, DB, или ваш самописный коннектор.

У каждого пользователя уникальный номер, если Midpoint видит существующею учётку AD с таким номером, то он эти две учётки связывает.

Если пользователь Midpoint без учётки в AD, получает роль сделай учётку AD, то учётка в AD создаётся, при этом генерирует уникальный name для AD и Midpoint.

У нас есть несколько пользователей с минимально заполненными данными. Архетип им не назначен (чёрные в списке), но лучше чтобы архетип был сразу такой же, как и в ресурсе при создании AD учётки см. конец главы III.

Идем в ресурс Windows MS AD и добавляем Object Type в Resources\Windows MS AD\Schema Handling\Object type\Add object type

Заполняем как на картинках, имя MS AD account

При создании учётки выдаём архетип Person, это просто хорошая практика всё расскладывать по своим архетипам, это сильно поможет в авторизации.

Scheme Handling Object Type создан теперь настраиваем его. Заходим в Resources\Windows MS AD\Schema Handling\Object type\MS AD account

Показываю и объясняю на картинках, в конце будет код для вставки

Mapping Inbound

В 4.9 заметные визуальные изменения в mappings. Появились кружочки — сильный миаппинг чёрный, слабый белый. Name маппинга теперь стал обязательным, уникальным и нельзя его редактировать!!!

01 in — используется только для корреляции, это в настройках маппинга выбрано в Use for

02 in — хочу писать sAMAccountName в nickName в Midpoint, но слабо хочу, если уже заполнено, то не писать — это для случая, когда у нового c пустым nickName пользователя в Midpoint уже есть учётка в AD

03 in — хочу писать sAMAccountName в name в Midpoint, а вот это уже сильно хочу. В Midpoint Name используется в качестве логина в его GUI и пользователь конечно будет помнить только свой логин в AD , так что есть смысл.

04 in write OU to locality — пищут dn без cn в locality для далеко идущих планов. Скрипт как раз убирает первый cn из dn

return ((basic.stringify(input).split(',')).tail()).join(',');

Скрипт, который работал в 4.8.4 в 4.9 не работает, пришлось добавить:

basic.stringify — Evolveum уже ответил что все правильно так и должно быть, должно не работать!

Mapping Outbound

Мапинги добавлялись по очереди номер в название возрастал, но в списке они сортируются не по названию а по ещё чему-то.

Тут все мапинги, необходимые для создания учетки MS AD и в основном AS IS кроме:

06 out new script for OU — пользователя нужно положить в OU если locality заполнено то пытается положить туда при первом разе и при всех следующих синхронизациях. Если же там пусто кладёт в New_Employees

OU выдаёт script

if (locality)  { dn_value = 'CN=' + nickName + ',' + locality } else { baseContext = basic.getResourceIcfConfigurationPropertyValue(resource, 'baseContext') dn_value = 'CN=' + nickName + ',OU=New_Employees,OU=OOO_ODIN,' + baseContext } return dn_value

08 out change pass on next login — ставим на учётке AD пользователя сменить пароль при первом заходе. Script передает нужное для этого значение

return "0"

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

"add".equals(operation.toString()) && midpoint.isEvaluateNew()

09 out — Тут собираем userPrincipalName сам он почему -то не собирается, это пригодится, если будет создавать почту Exchange

return nickName + "@168testserverhome.com"

Synchronization

Я не планирую создавать пользователей Midpoint из пользователей AD так что только Synchronize

Correlation rules

Activation Configuration

Добавляем Outbound

Выбираем первый Administrative status и заполняем

Если в Midpoint блокируется учётка, она блокируется в AD

Credentials configuration

Добавляем Outbound и заполняем

При создание учётки в AD нужен какой-то пароль, можно было всем выдавать один и тот же пароль, а можно генерировать случайный. Мы его передаём с Strength слабо, так что он будет передавать только при создании. Нормальный пароль AD кто-нибудь поставит при выдаче сотруднику ПК!

Код Resources\Windows MS AD\Schema Handling\Object type\MS AD account

<schemaHandling>                 <objectType id="5">             <kind>account</kind>             <intent>intent  MS AD account</intent>             <displayName>MS AD account</displayName>             <default>true</default>             <delineation>                 <objectClass>ri:user</objectClass>             </delineation>             <focus>                 <type>c:UserType</type>                 <archetypeRef oid="00000000-0000-0000-0000-000000000702" relation="org:default" type="c:ArchetypeType">                     <!-- Person -->                 </archetypeRef>             </focus>             <attribute id="18">                 <ref>ri:sn</ref>                 <outbound>                     <name>03 out</name>                     <strength>strong</strength>                     <source>                         <path>familyName</path>                     </source>                 </outbound>             </attribute>             <attribute id="20">                 <ref>ri:givenName</ref>                 <outbound>                     <name>01 out</name>                     <strength>strong</strength>                     <source>                         <path>givenName</path>                     </source>                 </outbound>             </attribute>             <attribute id="24">                 <ref>ri:employeeNumber</ref>                 <outbound>                     <name>10 out</name>                     <strength>strong</strength>                     <source>                         <path>personalNumber</path>                     </source>                 </outbound>                 <inbound id="742">                     <name>01 in</name>                     <strength>strong</strength>                     <target>                         <path>personalNumber</path>                     </target>                     <use>correlation</use>                 </inbound>             </attribute>             <attribute id="37">                 <ref>ri:cn</ref>                 <outbound>                     <name>04 out</name>                     <strength>strong</strength>                     <source>                         <path>nickName</path>                     </source>                 </outbound>             </attribute>             <attribute id="104">                 <ref>ri:sAMAccountName</ref>                 <outbound>                     <name>05 out</name>                     <strength>strong</strength>                     <source>                         <path>nickName</path>                     </source>                 </outbound>                 <inbound id="838">                     <name>02 in</name>                     <strength>weak</strength>                     <target>                         <path>nickName</path>                     </target>                 </inbound>                 <inbound id="839">                     <name>03 in</name>                     <strength>strong</strength>                     <target>                         <path>name</path>                     </target>                 </inbound>             </attribute>             <attribute id="105">                 <ref>ri:dn</ref>                 <outbound>                     <name>06 out new script for OU</name>                     <strength>strong</strength>                     <source>                         <path>locality</path>                     </source>                     <source>                         <path>nickName</path>                     </source>                     <expression>                         <script>                             <code>if (locality)  { dn_value = 'CN=' + nickName + ',' + locality } else { baseContext = basic.getResourceIcfConfigurationPropertyValue(resource, 'baseContext') dn_value = 'CN=' + nickName + ',OU=New_Employees,OU=OOO_ODIN,' + baseContext } return dn_value</code>                         </script>                     </expression>                 </outbound>                 <inbound id="775">                     <name>04 in write OU to locality</name>                     <strength>strong</strength>                     <expression>                         <script>                             <code>return ((basic.stringify(input).split(',')).tail()).join(',');</code>                         </script>                     </expression>                     <target>                         <path>locality</path>                     </target>                 </inbound>             </attribute>             <attribute id="106">                 <ref>ri:displayName</ref>                 <outbound>                     <name>07 out</name>                     <strength>strong</strength>                     <source>                         <path>nickName</path>                     </source>                 </outbound>             </attribute>             <attribute id="328">                 <ref>ri:middleName</ref>                 <outbound>                     <name>02 out</name>                     <strength>strong</strength>                     <source>                         <path>additionalName</path>                     </source>                 </outbound>             </attribute>             <attribute id="554">                 <ref>ri:pwdLastSet</ref>                 <limitations id="557">                     <access>                         <read>true</read>                         <add>true</add>                         <modify>false</modify>                     </access>                 </limitations>                 <fetchStrategy>explicit</fetchStrategy>                 <outbound>                     <name>08 out change pass on next login</name>                     <strength>strong</strength>                     <expression>                         <script>                             <code>// -1 next logon reset password required // 0 no previous loggon return "0"</code>                         </script>                     </expression>                     <condition>                         <script>                             <code>"add".equals(operation.toString()) &amp;&amp; midpoint.isEvaluateNew()</code>                         </script>                     </condition>                 </outbound>             </attribute>             <attribute id="699">                 <ref>ri:userPrincipalName</ref>                 <outbound>                     <name>09 out</name>                     <strength>strong</strength>                     <source>                         <path>nickName</path>                     </source>                     <expression>                         <script>                             <code>return nickName + "@168testserverhome.com"</code>                         </script>                     </expression>                 </outbound>             </attribute>             <attribute id="770">                 <ref>ri:distinguishedName</ref>             </attribute>             <activation>                 <administrativeStatus>                     <outbound id="794">                         <name>Just Block</name>                         <strength>strong</strength>                         <source>                             <path>activation/administrativeStatus</path>                         </source>                     </outbound>                 </administrativeStatus>                 <lockoutStatus/>             </activation>             <credentials>                 <password>                     <outbound id="765">                         <name>initial</name>                         <strength>weak</strength>                         <expression>                             <generate>                                 <mode>policy</mode>                                 <valuePolicyRef oid="00000000-0000-0000-0000-000000000003" type="c:ValuePolicyType" xsi:type="c:ObjectReferenceType"/>                             </generate>                         </expression>                     </outbound>                 </password>             </credentials>             <correlation>                 <correlators>                     <items id="820">                         <name>personalNumber correlation</name>                         <item id="821">                             <ref>personalNumber</ref>                         </item>                         <composition/>                     </items>                 </correlators>             </correlation>             <synchronization>                 <reaction id="755">                     <situation>linked</situation>                     <actions>                         <synchronize id="756"/>                     </actions>                 </reaction>                 <reaction id="757">                     <situation>unlinked</situation>                     <actions>                         <link id="758"/>                     </actions>                 </reaction>                 <reaction id="835">                     <situation>deleted</situation>                     <actions>                         <deleteResourceObject id="836"/>                     </actions>                 </reaction>             </synchronization>         </objectType>     </schemaHandling>

Пока это всё, что надо настроить в ресурсе, но нам нужна роль! Создаём простую чёрную роль под названием MS AD account 1.0 в Inducemente выбираем Resource Windows MS AD c intent MS AD account.

В коде это выглядит так:

<inducement id="2">         <construction>             <resourceRef oid="b8618fba-cf8b-416c-8e3b-32ea34cf003d" relation="org:default" type="c:ResourceType">                 <!-- Windows MS AD -->             </resourceRef>             <kind>account</kind>             <intent>intent  MS AD account</intent>         </construction>         <focusType>c:UserType</focusType>     </inducement>

OID Resource Windows MS AD у каждой установки будет отличаться.

Идём в Татьяну Петровну, выдаём роль MS AD account 1.0 (вручную через Assigment в ней) и смотрим на неё в списке пользователь!

Татьяна Петровна позеленела — потому что получила архетип Person (стандартный уже имеется) потому что в Resources\Windows MS AD в Schema Handling\Object type\MS AD account мы в Basic прописывали давать пользователям архетип Person, если случается привязка. Так же Midpoint заполнил ей Full Name. Также в Name ей записался sAMAccountName из AD, в который он попал из nickName в Midpoint!

И всё бы хорошо, но что это за логин TaniyushkaB, кто его так забил, да и откуда он вообще там… нужно генерировать nickName из имя отчество фамилия в момент предшествующий созданию AD аккаунта, да ещё и проверять, что такого уже нет в AD и Midpoint!

Создаём простую чёрную роль под названием MS AD account 2.0, которая полностью повторят версию 1.0.

Перед </role> вставляем:

<inducement id="2">         <construction>             <resourceRef oid="b8618fba-cf8b-416c-8e3b-32ea34cf003d" relation="org:default" type="c:ResourceType">                 <!-- Windows MS AD -->             </resourceRef>             <kind>account</kind>             <intent>intent  MS AD account</intent>         </construction>         <focusType>c:UserType</focusType>     </inducement>

Также перед </role> вставляем:

<inducement id="22">         <focusMappings>             <mapping id="2222">                 <name>Generate uniq nickName for AD and Midpoint</name>                 <lifecycleState>active</lifecycleState>                 <strength>strong</strength>                 <source>                     <path>c:givenName</path>                 </source>                 <source>                     <path>c:familyName</path>                 </source>                 <source>                     <path>c:additionalName</path>                 </source>                 <expression>                     <script>                         <code>import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.midpoint.prism.query.OrderDirection; import com.evolveum.midpoint.prism.path.ItemPath;  iterationToken = 0 is_it_ok = false resource_oid = "b8618fba-cf8b-416c-8e3b-32ea34cf003d" resource_kind = "ACCOUNT" resource_intent = "intent  MS AD account"  do { userGivenName = basic.stringify(givenName)?.tr(' ', '') userFamilyName = basic.stringify(familyName)?.tr(' ', '') useradditionalName = basic.stringify(additionalName)?.tr(' ', '') national_letters =['Я','я','Ю','ю','Ч','ч','Ш','ш','Щ','щ','Ж','ж','А','а','Б','б','В','в','Г','г','Д','д','Е','е','Ё','ё','Э','э','З','з','И','и','Й','й','К','к','Л','л','М','м','Н','н', 'О','о','П','п','Р','р','С','с','Т','т','У','у','Ф','ф','Х','х','Ц','ц','Ы','ы','Ь','ь','Ъ','ъ',' '] latin_letters =['Ya','ya','Yu','yu','Ch','ch','Sh','sh','Sh','sh','Zh','zh','A','a','B','b','V','v','G','g','D','d','E','e','E','e','E','e','Z','z','I','i','J','j','K','k','L','l','M','m','N','n', 'O','o','P','p','R','r','S','s','T','t','U','u','F','f','H','h','C','c','Y','y','','','','','']   for( i = 0; i &lt; national_letters.size(); i++) { userGivenName  = userGivenName?.replace(national_letters[i],latin_letters[i]); userFamilyName  = userFamilyName?.replace(national_letters[i],latin_letters[i]); useradditionalName  = useradditionalName?.replace(national_letters[i],latin_letters[i]); }  if ((iterationToken.toInteger() &amp; 1) == 0)  { second_letter = iterationToken.toInteger() / 2; first_letter = second_letter.toInteger() + 1; } else { first_letter = (iterationToken.toInteger() + 1) / 2; second_letter = first_letter; }   if(first_letter.toInteger() &gt; userGivenName.length() &amp;&amp; second_letter.toInteger() &gt; useradditionalName.length()) { user_number = iterationToken.toInteger() first_full = userGivenName.length() second_full = useradditionalName.length() if(useradditionalName.length() != 0) {     name_login_for_user = userGivenName.substring(0,first_letter.toInteger()) + useradditionalName.substring(0,second_letter.toInteger()) + userFamilyName          def query = midpoint.queryFor(ShadowType.class, "resourceRef matches (oid = '" + resource_oid + "') and kind = '" + resource_kind + "' and intent = '" + resource_intent + "' and attributes/cn = '" + name_login_for_user + "'")      def result_ad_login = midpoint.searchObjects(query);           if (midpoint.isUniquePropertyValue(user, 'name', name_login_for_user.toString()) &gt; !result_shadow_search)     {return name_login_for_user     is_it_ok = true}      }  else {return userGivenName.substring(0,first_full.toInteger()) + userFamilyName  + user_number} } else {if (first_letter.toInteger() &gt; userGivenName.length()) {     first_letter = userGivenName.length(); } if (second_letter.toInteger() &gt; useradditionalName.length()) {     second_letter = useradditionalName.length(); }  name_login_for_user = userGivenName.substring(0,first_letter.toInteger()) + useradditionalName.substring(0,second_letter.toInteger()) + userFamilyName   def query = midpoint.queryFor(ShadowType.class, "resourceRef matches (oid = '" + resource_oid + "') and kind = '" + resource_kind + "' and intent = '" + resource_intent + "' and attributes/sAMAccountName = '" + name_login_for_user + "'")  def result_ad_login = midpoint.searchObjects(query);    if (midpoint.isUniquePropertyValue(user, 'name', name_login_for_user.toString()) &amp;&amp; !result_ad_login) {return name_login_for_user is_it_ok = true}  } iterationToken = iterationToken + 1 } while (!is_it_ok)</code>                     </script>                 </expression>                 <target>                     <path>nickName</path>                 </target>             </mapping>         </focusMappings>         <condition>             <source>                 <path>c:givenName</path>             </source>             <source>                 <path>c:familyName</path>             </source>             <source>                 <path>c:nickName</path>             </source>             <expression>                 <script>                     <code>if (basic.isEmpty(nickName)) {if (!basic.isEmpty(givenName)) {if (!basic.isEmpty(familyName)) { return true }}} else { return false }</code>                 </script>             </expression>         </condition>     </inducement>

Что делает этот кусок. Это в роли маппинг в атрибут в пользователе nickName. Он берет givenName familyName additionalName меняет кириллицу на латиницу и собирает логин по формуле первая буква имени плюс фамилия, первая буква имени + первая буква отчества(если есть) + фамилия и так далее если буквы кончается ставит цифры. Так как это маппинг он сработает до части вызывающий создание учетки AD.

ГЛАВНОЕ УСЛОВИЕ: У пользователя должно быть имя и фамилия, nickName должен быть пустым. Если эти условия не выполнены и nickName не сгенерировался, попытка создать учетку всё равно будет предпринята с sAMAccountName null естественного второго пользователя AD с логином null уже не создаться будет явная ошибка…. и это пока оказывается лучшим вариантом, если вешать доп условия на создание учетки AD то он будет её отзывать при каждом невыполнение этого условия, лучше пусть пытается создавать всегда раз роль MS AD account 2.0 назначена, легче следить за тем чтобы всегда были имя и фамилия.

Еще один нюанс: Когда мы проверяем уникальность логина в AD, мы это далем не в AD а в Midpoint. У нас есть данные об учетках AD на момент реконсиляции Resources\Windows MS AD в Schema Handling\Object type\MS AD account в них и проверяется уникальность. Мало вероятно но может случится так что в AD после синхронизации с Midpoint создается учетка и Midpoint о ней ничего не знает. Просто не создавайтей вручную в AD учетки раз у вас IDM! Вот сколько учеток увидел Resources\Windows MS AD в Schema Handling\Object type\MS AD account

В скрипте следует изменить на свои

 resource_oid = "b8618fba-cf8b-416c-8e3b-32ea34cf003d"   resource_kind = "ACCOUNT"   resource_intent = "intent  MS AD account"

это тоже что в первой части направляем в наш Resources\Windows MS AD в Schema Handling\Object type\MS AD account.

Раздал всем пользователям без учетки AD роль MS AD account 2.0.

У нас много граждан по фамилии Кот да еще и первые буквы имени и отчества у них совпадают — ничего страшного Midpoint разобрался! Посмотрите на Ирину Васильевну Стар логин IVStar, а должен был быть IStar однофамельцев то нет рядом, а вот в AD уже есть логин istar(видно на предыдущем скриншоте) поэтому получила IVStar.

Только вот TaniyushkaB выбивается из общей логики… Назначаем ей роль MS AD account 2.0 и одновременно отзываем MS AD account 1.0. Ничего не происходит потому что все довольны nickName есть ничего делать не надо. Удалим nickName и вот теперь да он перегенерировался и сменился в AD и стал как положено TBor… второй раз удалять не надо, а то Midpoint его изменит на следующий свободный TPBor… ну ладно, давайте третий раз удалим — вернулся TBor, всё правильно — первый свободный в переборе всё ок!

Делаем вывод, если хотим пересчитать nickName, то удаляем его. А это уже политика — например смена фамилии в Midpoint, сейчас ни на что автоматом это не влияет, но мы можем добавить в роль MS AD account 2.0 политику, которая при изменении в атрибуте «фамилия» будет удалять nickName и запускать recompute пользователя!

В коде роли MS AD account 2.0 перед </role> вставляем:

<inducement id="222">         <policyRule>             <name>Delete nickName if familyName modified</name>             <policyConstraints>                 <or id="14">                      <modification id="16">                         <item>c:familyName</item>                     </modification>                  </or>             </policyConstraints>             <policyActions>                 <scriptExecution id="5">                     <name>some script</name>                     <executeScript xmlns:s="http://midpoint.evolveum.com/xml/ns/public/model/scripting-3">                         <s:pipeline list="true">                             <s:action>                                 <s:type>execute-script</s:type>                                 <s:parameter>                                     <s:name>script</s:name>                                     <s:value>                                         <code> import com.evolveum.midpoint.xml.ns._public.common.common_3.* import com.evolveum.midpoint.prism.delta.builder.* import com.evolveum.midpoint.model.api.* import javax.xml.namespace.QName import com.evolveum.midpoint.prism.polystring.PolyString  my_info = new PolyString("") delta = prismContext.deltaFor(UserType.class).item(UserType.F_NICK_NAME).replace(my_info).asObjectDelta(input.oid) midpoint.modifyObject(delta,  ModelExecuteOptions.createRaw()) midpoint.recompute(UserType.class, input.oid) </code>                                     </s:value>                                 </s:parameter>                             </s:action>                         </s:pipeline>                     </executeScript>                 </scriptExecution>             </policyActions>         </policyRule>         <focusType>c:UserType</focusType>     </inducement>

УТатьяны Петровны Бор знаменательное событие в жизни — смена фамилии, правда мы не знаем основания — свадьба или развод, но IDM это не важно, теперь она Земляникина в карточке Midpoint, и если смотреть в её History — это сразу триггерит несколько изменений, вот самое главное в AD.

Мы всё добавляли кодом, но в роли MS AD account 2.0 почти всё в читабельной форме тоже видно.

Ещё один нюанс — так как мы планировали что может быть вариант когда учётка AD уже есть у пользователя без роли AD, то вместе с привязыванием надо ему так же выдавать роль AD, хорошо для наглядности, учётку и потом можно будет отобрать — не выдав не отобрать!

Добавляем пустой inbound маппинг в Resources\Windows MS AD в Schema Handling\Object type\MS AD account в качествеFrom resource attribute* выбираем sAMAccountName, а имя 05 in assign to role AD account.

Находим его в RAW сode и доводим до вида

<inbound id="796">                     <name>05 in assign to role AD account</name>                     <strength>strong</strength>                     <expression>                         <assignmentTargetSearch>                             <targetType>c:RoleType</targetType>                             <oid>1cae659f-69f2-43b8-b075-8226d718eef9</oid>                         </assignmentTargetSearch>                     </expression>                     <target>                         <path>$focus/assignment</path>                     </target>                 </inbound> 

<oid> — OID роли MS AD account 2.0 его видно в Repository Objects\All Objects в Type выбрать Role.

Надо вставлять кодом потому что вставление через GUI не прописали!

Чтобы привязка сработала надо учитывать структурную тупость Midpoint (глюком это не признаётся) чтобы аккаунт AD в ресурсе привязался к aккаунту Midpoint — у последнего должен быть такой же архетип, какой выдаёт AD ресурс при создании AD аккаунта… помните в списках пользователей Татьяна Петровна была чёрная, а при создании AD учётки она позеленела! Вот а у нас все пользователи при создании из HR ресурса были чёрными (без архетипа), а надо было сразу делать зелёными, если хотим, чтобы они привязывались к существующим AD аккаунтам!

ОДНАКО: В 4.9 вышеописанная практика неявным и совершенно неожиданным образом ломает в user вкладку All accesses, где должны показываться все явно и не явно выданные роли, получается роль выдаётся два раза и Midpointt 4.9 клинит на странице пользователя All accesses в отличие от предыдущих версий… в Evolveum сообщил, маппинг отключил — в любом случае он хорош только для миграции для одноразового использования, после уже надо делать AD учётки из Midpoint через роль.

IV Настройка привязки Midpoint к группам из MS AD

В 4.9 полностью убили GUI и представление о том как настраивать Association (сами они это называют membership, я буду называть это членство) старым способом, ввели новый (разнесли его по трём местам и максимально запутали) docs.evolveum.com/midpoint/reference/master/resources/entitlements/ но так как AD connector 3.8 не работает с AD MS особенно в части group, всё буду настраивать по старому, тем более и коннектор у нас 3.7.2, но придётся делать это в слепую!

Будем реализовывать следующую схему — можно добавлять пользователей в группы и в AD и в Midpoint и всё синхронизируется.

Перед началом я ограничиваю поиск в AD конкретной OU

В Resources\Windows MS AD\Connector Configuration в Base context пишу

OU=OOO_ODIN,DC=168testserverhome,DC=com

И в Resources\Windows MS AD\Schema Handling\Object type\MS AD account\Mapping\Outbound в мапинге 06 out new script for OU меняю скрипт

if (locality)  { dn_value = 'CN=' + nickName + ',' + locality } else { baseContext = basic.getResourceIcfConfigurationPropertyValue(resource, 'baseContext') dn_value = 'CN=' + nickName + ',OU=New_Employees,' + baseContext } return dn_value

Для начала создаём архетип под роли для групп. В Archetypes\New archetypes имя AD Group ArcheType и пока настраиваем только отображение, в Archetypes\AD Group ArcheType\Archetype policy\Display\Icon заполняем согласно своим визуальным предпочтениям.

Идём в ресурс Windows MS AD и добавляем Object Type в Resources\Windows MS AD\Schema Handling\Object type\Add object type.

Заполняем как на картинке, имя MS AD group

Scheme Handling Object Type создан, теперь настраиваем его. Заходим в Resources\Windows MS AD\Schema Handling\Object type\MS AD group.

Показываю и объясняю на картинках, в конце будет код для вставления.

Mapping Inbound

Outbound нет, ну и остальное буквально. Можно сделать так чтобы делать группа AD из роли Midpoint, но я не делаю.

01 in g — тут скрипт, собираю имя, которое точно будет уникальным в Midpoint просто добавляю в начале «ADG:» с уверенностью, что никто и ни что во всех системах у нас так не делает.

"ADG:" + basic.stringify(input)

Synchronization

Correlation

Тут всё, самое главное будет настраивать в архетипе и вообще в другом Schema Handling\Object type

Весь код Resources\Windows MS AD\Schema Handling\Object type\MS AD group

<objectType id="847">             <kind>entitlement</kind>             <intent>intent MS AD group</intent>             <displayName>MS AD group</displayName>             <delineation>                 <objectClass>ri:group</objectClass>             </delineation>             <focus>                 <type>c:RoleType</type>                 <archetypeRef oid="e9eda47b-b097-4814-9605-7177a2482fa1" relation="org:default" type="c:ArchetypeType">                     <!-- AD Group ArcheType -->                 </archetypeRef>             </focus>             <attribute id="849">                 <ref>ri:cn</ref>                 <inbound id="850">                     <name>01 in g</name>                     <strength>strong</strength>                     <expression>                         <script>                             <code>"ADG:" + basic.stringify(input)</code>                         </script>                     </expression>                     <target>                         <path>name</path>                     </target>                 </inbound>             </attribute>             <attribute id="851">                 <ref>ri:displayName</ref>                 <inbound id="852">                     <name>02 in g</name>                     <strength>strong</strength>                     <target>                         <path>displayName</path>                     </target>                 </inbound>             </attribute>             <attribute id="853">                 <ref>ri:distinguishedName</ref>                 <inbound id="854">                     <name>03 in g</name>                     <strength>strong</strength>                     <target>                         <path>identifier</path>                     </target>                 </inbound>             </attribute>             <correlation>                 <correlators>                     <items id="865">                         <name>Correlate by identifier and dn</name>                         <item id="866">                             <ref>identifier</ref>                         </item>                     </items>                 </correlators>             </correlation>             <synchronization>                 <reaction id="856">                     <situation>unmatched</situation>                     <actions>                         <addFocus id="857"/>                     </actions>                 </reaction>                 <reaction id="858">                     <situation>linked</situation>                     <actions>                         <synchronize id="859"/>                     </actions>                 </reaction>                 <reaction id="860">                     <situation>unlinked</situation>                     <actions>                         <link id="861"/>                     </actions>                 </reaction>                 <reaction id="862">                     <situation>deleted</situation>                     <actions>                         <deleteResourceObject id="863"/>                     </actions>                 </reaction>             </synchronization>         </objectType>

Нам нужно настроить членство(Association) в ресурсе Resources\Windows MS AD\ находим код Schema Handling\Object type\MS AD Account и вставляем перед </objectType>

Код

<association id="306">                 <ref>AD group membership to Midpoint</ref>                 <inbound id="478">                     <strength>normal</strength>                     <channel>http://midpoint.evolveum.com/xml/ns/public/common/channels-3#reconciliation</channel>                     <expression>                         <assignmentTargetSearch>                             <targetType>RoleType</targetType>                             <filter>                                 <q:equal>                                     <q:path>identifier</q:path>                                     <expression>                                         <script>                                             <code>                                                 return basic.getAttributeValue(entitlement, 'dn')                                             </code>                                         </script>                                     </expression>                                 </q:equal>                             </filter>                         </assignmentTargetSearch>                     </expression>                     <target>                         <path>assignment</path>                     </target>                 </inbound>                 <kind>entitlement</kind>                 <intent>intent MS AD group</intent>                 <direction>objectToSubject</direction>                 <associationAttribute>ri:member</associationAttribute>                 <valueAttribute>ri:dn</valueAttribute>                 <explicitReferentialIntegrity>false</explicitReferentialIntegrity>             </association>

Тут мы устанавливаем связь между двумя Schema Handling\Object type через пользователя. Midpoint хочет добавить member роли под AD группу, но для этого нужен dn, а его знает только Schema Handling\Object type\MS AD Account.

Тут ещё обращаем внимание на код в <inbound>…</inbound> он при синхронизации пользователя выдаёт ему Midpoint роли AD group в которых он в AD

ОДНАКО: В версии 4.9 сейчас глюк, если редактировать добавлять association это ломает реконсиляцию с ошибкой com.evolveum.midpoint.xml.ns._public.common.common_3.VariableBindingDefinitionType.getPath()» because «sourceType» is null support.evolveum.com/projects/midpoint/work_packages/9932 обещают исправить в 4.9.1

Временное решение после редактирования перестартануть Midpoint и также иногда надо удалить все Shadow на ресурсе.

Теперь идём в архетипы Archetypes\AD Group ArcheType в код добавляем перед </archetype>

Код

<inducement id="7">         <construction>             <resourceRef oid="b8618fba-cf8b-416c-8e3b-32ea34cf003d" relation="org:default" type="c:ResourceType">                 <!-- Windows MS AD -->             </resourceRef>             <kind>account</kind>             <intent>intent  MS AD account</intent>             <association id="28">                 <ref>AD group membership to Midpoint</ref>                 <outbound>                     <expression>                         <associationFromLink>                             <projectionDiscriminator xsi:type="c:ShadowDiscriminatorType">                                 <kind>entitlement</kind>                                 <intent>intent MS AD group</intent>                             </projectionDiscriminator>                         </associationFromLink>                     </expression>                 </outbound>             </association>         </construction>         <order>2</order>         <focusType>UserType</focusType>     </inducement>

OID — ресурса Windows MS AD

AD group membership to Midpoint — должно быть таким же, как в ресурсе

Здесь прописано самое главное, где роли искать к кому и как прицепить пользователя

Создаём, в AD группу включаем в неё пользователя. Запускаем реконсиляцию Schema Handling\Object type\MS AD Group

Для этого в Resources\Windows MS AD\Defined Task создаём таск, главное указать Kind и Intent и будем его запускать вручную. Если все зелёно (справа вверху) то ок, если красно, то смотрим в task’е в Result и Errors.

Роль, привязанная к группе появилась, но членов в ней нет, потому что это случится в пользовательской реконсиляции.

Запускаем реконсиляцию пользователей Schema Handling\Object type\MS AD Account и всё у всех появляется

У пользователя роль

У роли пользователь

Возможна ситуация, что при синхронизации пользователя он есть в AD группе для которой нет ещё роли в Midpoint — выдачи не случится, надо будет ждать реконсиляции групп и следующей реконсиляции пользователей. Но можно создать пустую (не привязанной к AD группе) роль для AD группы. Для этого в Midpoint есть createOnDemand и populateObject

Меняем код членства в Schema Handling\Object type\MS AD Account на

<association id="306">                 <ref>AD group membership to Midpoint</ref>                 <inbound id="478">                     <strength>normal</strength>                     <channel>http://midpoint.evolveum.com/xml/ns/public/common/channels-3#reconciliation</channel>                     <expression>                         <assignmentTargetSearch>                             <targetType>RoleType</targetType>                             <filter>                                 <q:equal>                                     <q:path>identifier</q:path>                                     <expression>                                         <script>                                             <code>                                                 return basic.getAttributeValue(entitlement, 'dn')                                             </code>                                         </script>                                     </expression>                                 </q:equal>                             </filter>                             <createOnDemand>true</createOnDemand>                             <populateObject>                                 <populateItem>                                     <expression>                                         <script>                                             <code>                                                 "ADG:" + basic.getAttributeValue(entitlement, 'cn')                                             </code>                                         </script>                                     </expression>                                     <target>                                         <path>name</path>                                     </target>                                 </populateItem>                                 <populateItem>                                     <expression>                                         <script>                                             <code>                                                 basic.getAttributeValue(entitlement, 'dn')                                             </code>                                         </script>                                     </expression>                                     <target>                                         <path>identifier</path>                                     </target>                                 </populateItem>                                 <populateItem>                                     <expression>                                         <assignmentTargetSearch>                                             <targetType>ArchetypeType</targetType>                                             <filter>                                                 <q:equal>                                                     <q:path>name</q:path>                                                     <expression>                                                         <value>AD Group ArcheType</value>                                                     </expression>                                                 </q:equal>                                             </filter>                                         </assignmentTargetSearch>                                     </expression>                                     <target>                                         <path>assignment</path>                                     </target>                                 </populateItem>                             </populateObject>                         </assignmentTargetSearch>                     </expression>                     <target>                         <path>assignment</path>                     </target>                 </inbound>                 <kind>entitlement</kind>                 <intent>intent MS AD group</intent>                 <direction>objectToSubject</direction>                 <associationAttribute>ri:member</associationAttribute>                 <valueAttribute>ri:dn</valueAttribute>                 <explicitReferentialIntegrity>false</explicitReferentialIntegrity>             </association>

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

А вот другой вариант — вы хотите чтобы у пользователя было членство только в AD группах, в которых он есть в ролях в Midpoint под эти роли. То есть пользователь получает только AD группы выданные через роли в Midpoint, а группы выданные через консоль AD будут удаляться при синхронизации с Midpoint.

Меняем код членства в Schema Handling\Object type\MS AD Account на

<association id="306">                 <ref>AD group membership to Midpoint</ref>                 <tolerant>false</tolerant>                 <kind>entitlement</kind>                 <intent>intent MS AD group</intent>                 <direction>objectToSubject</direction>                 <associationAttribute>ri:member</associationAttribute>                 <valueAttribute>ri:dn</valueAttribute>                 <explicitReferentialIntegrity>false</explicitReferentialIntegrity>             </association>

Добавлена не толерантность <tolerant>false</tolerant>

Теперь запускаем синхронизацию Schema Handling\Object type\MS AD Account и все группы которые есть у пользователя в AD, но их нет в виде ролей у него в Midpoint исчезли. Да мы даже можем увидеть это в пользователе в History (безопасникам понравится)!

Ещёстоит сказать о группах — Midpoint делает то, что мы от него хотим — если мы выдаём пользователю роль AD группы, он нам молча делает этому пользователю AD учётку, что вот нас в этом примере совсем не устраивает, потому что nickName не генерируется без роли MS AD account 2.0. И если мы удаляем роль MS AD account 2.0, но у пользователя есть AD‑роль группа то учётка AD у него остаётся.

Это даже не минус, а прекрасная возможность для построения своих творческих IDM грабель, но мы воспользуемся встроенным механизмом Policy, который можно назвать еще SOD — отдельной кнопки в Midpoint для SOD нет, но вот по смыслу это Policy.

Если пользователь получает AD группу роль, то она не выдаётся, а administrator получает case на разбор.

В архетип групп Archetypes\AD Group ArcheType добавляем в inducement политику кодом

<inducement id="30">         <policyRule>             <name>User must have role MS AD account 2.0</name>             <policyConstraints>                 <requirement id="31">                     <targetRef oid="1cae659f-69f2-43b8-b075-8226d718eef9" relation="org:default" type="c:RoleType">                         <!-- MS AD account 2.0 -->                     </targetRef>                 </requirement>             </policyConstraints>             <policyActions>                 <approval id="35">                     <approverRef oid="00000000-0000-0000-0000-000000000002" relation="org:default" type="c:UserType">                         <!-- administrator -->                         <_metadata id="37">                             <provenance>                                 <acquisition id="38">                                     <actorRef oid="00000000-0000-0000-0000-000000000002" relation="org:default" type="c:UserType">                                         <!-- administrator -->                                     </actorRef>                                     <channel>http://midpoint.evolveum.com/xml/ns/public/common/channels-3#user</channel>                                     <timestamp>2024-11-20T06:54:42.638Z</timestamp>                                 </acquisition>                             </provenance>                         </_metadata>                     </approverRef>                 </approval>             </policyActions>             <evaluationTarget>assignment</evaluationTarget>         </policyRule>     </inducement>

Да и картинкой вот

Теперь выдаём пользователю любую AD роль группу, если у него нет роли MS AD account 2.0, он её не получает в administrator получает Case.

administrator смотрит в Cases\My work items и видит один кейс

Правильные действия administrator пойти в пользователя, выдать ему группу MS AD account 2.0, case не умный сам не закроется после выдачи, надо зайти в него и Approve. Неудобно? Да! Но главное мы предотвратили бездумное создание аккаунта AD с непонятно каким nickName, а в плане правильный или неправильный способ — тут у каждого свои грабли.

IV Настройка организационной структуры из OU MS AD

Как часть ролевой модели нам нужна организационная структура, для этого нужна хоть какая-то структура. Возьмём OU из MS AD, они в примере соответствуют отделам (более менее). Все, кто в отделе получат роли отдела и головную роль департамента.

ОДНАКО: Сквозное наследование из других родительских организационных единиц сейчас работает не так, как должно бы. В Evolveum сообщил. Почему то в OrgType inducement срабатывает как assignment, хотя по inducement права должны даваться только пользователю, а не роли — в этом вся суть Midpoint!

Для начала создаём архетип под организационные единицы. В Archetypes\New archetypes имя AD OU ArcheType и пока настраиваем только отображение, в Archetypes\AD Group ArcheType\Archetype policy\Display\Icon заполняем согласно своим визуальным предпочтениям

Идём в ресурс Windows MS AD и добавляем Object Type в Resources\Windows MS AD\Schema Handling\Object type\Add object type

Заполняем как на картинке, имя MS AD OrgUnit

Scheme Handling Object Type создан, теперь настраиваем его. Заходим в Resources\Windows MS AD\Schema Handling\Object type\MS AD OrgUnit

Показываю и объясняю на картинках в конце будет код для вставления.

Mapping Inbound

Outbound нет.

01 in ou — Собираем name скриптом

"ADOU:" + input

05 in ou — сюда пишем в каком OU наша OU

return ((basic.stringify(input).split(',')).tail()).join(',');

Synchronization

Код Resources\Windows MS AD\Schema Handling\Object type\MS AD OrgUnit

<objectType id="878">             <kind>generic</kind>             <intent>intent MS AD OrgUnit</intent>             <displayName>MS AD OrgUnit</displayName>             <delineation>                 <objectClass>ri:organizationalUnit</objectClass>             </delineation>             <focus>                 <type>c:OrgType</type>                 <archetypeRef oid="fd97bda5-6d7a-41ca-badb-f321fec3d9ff" relation="org:default" type="c:ArchetypeType">                     <!-- AD OU ArcheType -->                 </archetypeRef>             </focus>             <attribute id="888">                 <ref>ri:cn</ref>             </attribute>             <attribute id="891">                 <ref>ri:dn</ref>                 <inbound id="892">                     <name>02 in ou</name>                     <strength>strong</strength>                     <target>                         <path>identifier</path>                     </target>                 </inbound>                 <inbound id="899">                     <name>05 in ou</name>                     <strength>strong</strength>                     <expression>                         <script>                             <code>return ((basic.stringify(input).split(',')).tail()).join(',');</code>                         </script>                     </expression>                     <target>                         <path>locality</path>                     </target>                 </inbound>             </attribute>             <attribute id="893">                 <ref>ri:description</ref>                 <inbound id="894">                     <name>04 in ou</name>                     <strength>strong</strength>                     <target>                         <path>description</path>                     </target>                 </inbound>             </attribute>             <attribute id="901">                 <ref>ri:ou</ref>                 <inbound id="902">                     <name>01 in ou</name>                     <strength>strong</strength>                     <expression>                         <script>                             <code>"ADOU:" + input</code>                         </script>                     </expression>                     <target>                         <path>name</path>                     </target>                 </inbound>                 <inbound id="903">                     <name>03 in ou</name>                     <strength>strong</strength>                     <target>                         <path>displayName</path>                     </target>                 </inbound>             </attribute>             <correlation>                 <correlators>                     <items id="896">                         <name>ou corr dn and identifier</name>                         <item id="897">                             <ref>identifier</ref>                         </item>                     </items>                 </correlators>             </correlation>             <synchronization>                 <reaction id="880">                     <situation>unmatched</situation>                     <actions>                         <addFocus id="881"/>                     </actions>                 </reaction>                 <reaction id="882">                     <situation>unlinked</situation>                     <actions>                         <link id="883"/>                     </actions>                 </reaction>                 <reaction id="884">                     <situation>linked</situation>                     <actions>                         <synchronize id="885"/>                     </actions>                 </reaction>             </synchronization>         </objectType>

Запускать синхронизацию Schema Handling\Object type\MS AD OrgUnit рано! Нам надо продумать как OU в Midpoint будут строиться в дерево, для этого нам надо их друг в друга assignment, будем это делать через Object Template в ArcheType

Заходим в Object Templates\New object template и просто создаём пустой под именем AD OU Object Template

Заходим в него и добавляем в RAW передавать

</objectTemplate>

Код:

<item id="1">         <ref>assignment</ref>         <displayName>Assignment to OU form locality</displayName>         <mapping id="9">             <source>                 <path>locality</path>             </source>             <expression>                 <assignmentTargetSearch>                     <targetType>OrgType</targetType>                     <filter>                         <q:equal>                             <q:path>identifier</q:path>                             <expression>                                 <path>$user/locality</path>                             </expression>                         </q:equal>                     </filter>                     <createOnDemand>true</createOnDemand>                     <populateObject>                         <populateItem>                             <expression>                                 <script>                                     <code>                                                locality                                             </code>                                 </script>                             </expression>                             <target>                                 <path>name</path>                             </target>                         </populateItem>                         <populateItem>                             <expression>                                 <script>                                     <code>                                                 locality                                             </code>                                 </script>                             </expression>                             <target>                                 <path>identifier</path>                             </target>                         </populateItem>                         <populateItem>                             <expression>                                 <script>                                     <code>                                                 "populated"                                             </code>                                 </script>                             </expression>                             <target>                                 <path>documentation</path>                             </target>                         </populateItem>                         <populateItem>                             <expression>                                 <assignmentTargetSearch>                                     <targetType>ArchetypeType</targetType>                                     <filter>                                         <q:equal>                                             <q:path>name</q:path>                                             <expression>                                                 <value>AD OU ArcheType</value>                                             </expression>                                         </q:equal>                                     </filter>                                 </assignmentTargetSearch>                             </expression>                             <target>                                 <path>assignment</path>                             </target>                         </populateItem>                     </populateObject>                 </assignmentTargetSearch>             </expression>         </mapping>     </item>

Идём в Archetypes\AD Group ArcheType\Archetype policy и в Object template reference добавляем AD OU Object Template

Вот теперь можно запускать в ресурсе реконсиляцию Schema Handling\Object type\MS AD OrgUnit.

В Org.structure\All organization у нас появляется куча OU

А главное они собрались в дерево в Org.structure\Organization Tree. Все что не попало в дерево в Organization Tree будет валятся на первом уровне с другими деревьями.

Теперь надо разложить в OU пользователей. Для OU в MS AD нет member, нельзя сделать как с группами. Поэтому в ArcheType пользователей Person создаем Object Template который и будет расскладывать пользоватлей по OU на основе пользовательского атрибута locality.

К архетипу Person уже подключен Person Object Template, идём в него в Object template\Person Object Template.

В RAW коде добавляем перед </objectTemplate>

Код:

<item id="1">         <ref>assignment</ref>         <displayName>Assignment to OU form user locality</displayName>         <mapping id="9">             <name>its a mapping</name>             <strength>strong</strength>             <source>                 <path>locality</path>             </source>             <expression>                 <assignmentTargetSearch>                     <targetType>OrgType</targetType>                     <filter>                         <q:equal>                             <q:path>identifier</q:path>                             <expression>                                 <path>$user/locality</path>                             </expression>                         </q:equal>                     </filter>                 </assignmentTargetSearch>             </expression>         </mapping>     </item>

Теперь создаём в MS AD типовые роли типа ADG IT Level 1 до 3. Реконсилим Schema Handling\Object type\MS AD group чтобы они появились в Midpoint. Заходим в организационные единицы Level 1 и indecement в роль ADG:ADG IT Level 1 и тд до 3. Теперь в MS AD кладём Юлию Васильевну в OU=Level 1,OU=IT,OU=OOO_ODIN,DC=168testserverhome,DC=com до этого как и все новые сотрудники она была в OU=New_Employees,OU=OOO_ODIN,DC=168testserverhome,DC=com. Реконсилим Schema Handling\Object type\MS AD account и смотрим что у Юлии Васильевны в All accesses

Видим прямые Direct назначение и непрямые из организационной единцы Level 1 а именно роль AD группы ADG IT Level 1. Перекладываем Юлию Васильевну в MS AD в OU=Level 2,OU=IT,OU=OOO_ODIN,DC=168testserverhome,DC=com реконсилим Schema Handling\Object type\MS AD account и смотрим

Организационная единица сменилась на Level 2 и AD роль группа тоже сменилась!

Вот так можно быстро, а главное просто, начать в Midpoint работать с MS AD!

Файлы настроенного по статье и работающего Midpoint доступны на Github.


ссылка на оригинал статьи https://habr.com/ru/articles/862112/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *