Вступление
Давайте, я сразу объясню свою баянистость. Да, в интернетах полно мануалов. Да, полно пошаговых прохождений. Да, можете сказать, что все жевано пережевано. Но конкретно в моем случае, как это всегда и бывает, оказалась горстка "но":
Есть мануалы о том, как настроить связку NiFi и NiFi Registry со включенной аутентификацией и авторизацией. Но... используются самоподписанные серты.
Есть отдельные мануалы, как прикрутить коммерческий серт для NiFi; соответственно для NiFi Registry "кагбэ так же". Но взаимная аутентификация и авторизация будет происходить с использованеим Two way SSL... а у нас же LDAP... и обеспечить потом связность сладкой парочки с использованием только внешнего каталога у вас на голой интуиции не получится.
Есть мануалы по связке с LDAP и для NiFi, и для NiFi Registry. Нооо... как и в предыдущем "но", возникают вопросы, как обойтись потом только LDAP'ом, потому что у нас же еще NiFi Cli, а он в LDAP не умеет.
Иными словами, во всех мануалах есть маааленький нюанс: они покрывают только простейшие сценарии. Документации по комплексным связкам просто нет. Более того, в ходе настройки связки я столкнулся со сложностями, которые в буржуйнете встречаются всего несколько раз и все они либо без ответов, либо ответы не релевантны.
Что у нас есть и что мы хотим получить
У нас есть:
Коммерческий wildcard SSL/TLS сертификат;
Сервер каталогов, который умеет в LDAP (в моем случае Apache DS);
Сервер NiFi, на котором ведется разработка;
Сервер NiFi в продуктовом окружении;
Сервер NiFi Registry.
Мы хотим:
Аутентификацию, авторизацию и HTTPS. Тем более, NiFi не позволяет включить встроенные механизмы аутентификации без HTTPS;
Централизованное управление пользователями на сервере каталогов;
Версионирование flow и process-group в схожей с гитом манере;
Автоматизацию доставки и развертывания релизов с дева на прод.
Наш план:
Настройка Apache DS;
Создание Java Keystore и Java Truststore, включение HTTPS;
Настройка аутентификации через LDAP в NiFi;
Настройка аутентификации через LDAP в NiFi Registry;
Переопределение значений идентификации;
Настройка связки NiFi и NiFi Registry;
Трансфер данных из одного NiFi в другой с помощью NiFi Cli.
Соглашение об именовании
В нашем примере wildcard сертификат выдан на домен: *.love.you;
FQDN сервера с Apache DS: auth.love.you;
Учетная запись для подключения к Apache DS: uid=admin,ou=system; пароль по умолчанию для первого входа: secret;
Создадим в Apache DS раздел love.you: dc=love,dc=you;
Создадим в Apache DS пользователя nifiAdmin с администраторскими привилегиями и пользователя nifiUser без администраторских привилегий в NiFi и NiFi Registry;
Создадим в Apache DS группу nifiAdmins для администраторов и nifiUsers для пользователей в NiFi и NiFi Registry;
FQDN NiFi, где ведется разработка: nifi-deve.love.you;
FQDN NiFi Registry: nifi-re.love.you;
FQDN целевого (продуктового) NiFi: nifi.love.you;
Путь, по которому установлен NiFi: $NIFI_HOME;
Путь, по которому установлен NiFi Registry: $NIFI_REGISTRY_HOME;
Путь, по которому установлен NiFi Toolkit: $NIFI_TOOLKIT_HOME;
Путь, по которому сохранены сгенерированные контейнеры: /love/conf/cert;
Пароль для экспорта из PKCS12, для Java Keystore и Java Truststore:
sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
Apache DS
На самом деле, конечно же, на Apache DS свет клином не сошелся. Вы можете использовать любую службу или любой сервер каталогов по вашему вкусу. У нас для внутрикорпоративных целей используется Azure AD, а для "третьих лиц", которые и будут пользоваться NiFi, корпоративную AD'шку использовать не хотелось. Apache DS был выбран просто потому что он, ну, тоже Apache.
Процесс установки прост. Я люблю ставить из архивов, поэтому скачал архив, распаковал в любимое место, создал файл сервиса, запустил сервис. Подробности - на официальном сайте.
По умолчанию после запуска сервис начинает слушать 10389 порт. Для подключения к сервису потребуется Apache Directory Studio. Скачиваете, устанавливаете, запускаете.
В левой нижней секции окна программы правый клик мыши и создаете соединение New connection:
Укаызваете имя и параметры подключения:
На следующем шаге мастера указываете данные учетной записи администратора: uid=admin,ou=system и пароль secret. Проверяем подключение нажатием на кнопку Check Authentication:
По завершении мастера соединие устанавливается автоматически.
Теперь необходимо отредактировать схему. Цель редактирования - добавить атрибут member в objectclass inetOrgPerson. Выберите в LDAP Browser'е вхождение ou=schema правым кликом мыши и выберите Reload Entry:
Разверните загруженный список и повторите действия над вхождением cn=inetorgperson и далее над ou=objectClasses. Нас интересует вхождение m-oid=2.16.840.1.113730.3.2.2. Правый клик мыши и выберите Open With -> LDIF Entry Editor:
Добавьте строку m-may: member и сохраните изменения Ctrl+S:
Далее правый клик на соединении в левой нижней части окна и выберите Open Configuration:
Выбираем Advanced Partition configuration...
Нажимаем Add, заполняем поля ID и Suffix. По окончании сохраняем изменения нажатием Ctrl+S:
Теперь важный момент: изменения в схеме и созданный раздел станут доступны только после перезапуска службы. Так что идем в консоль сервера и перезапускаем службу. Теперь разрываем соединение и подключаемся снова. Раздел появился:
Далее заносим группы и пользователей. Самый простой способ - с помощью импорта LDIF файла. Скопируйте содержимое из-под спойлера в файл import.ldif и сохраните его.
import.ldif
dn: ou=people,dc=love,dc=you
objectclass: organizationalUnit
objectClass: extensibleObject
objectclass: top
ou: people
dn: ou=groups,dc=love,dc=you
objectclass: organizationalUnit
objectClass: extensibleObject
objectclass: top
ou: groups
dn: cn=nifiUsers,ou=groups,dc=love,dc=you
objectClass: groupOfUniqueNames
objectClass: top
cn: nifiUsers
uniqueMember: cn=nifiUser,ou=people,dc=love,dc=you
dn: cn=nifiAdmins,ou=groups,dc=love,dc=you
objectClass: groupOfUniqueNames
objectClass: top
cn: nifiAdmins
uniqueMember: cn=nifiAdmin,ou=people,dc=love,dc=you
dn: cn=nifiUser,ou=people,dc=love,dc=you
objectclass: inetOrgPerson
objectclass: organizationalPerson
objectclass: person
objectclass: top
cn: nifiUser
description: A nifiUser user
sn: nifiUser
uid: nifiUser
mail: nifiUser@love.you
userpassword: password
member: cn=nifiUsers,ou=groups,dc=love,dc=you
dn: cn=nifiAdmin,ou=people,dc=love,dc=you
objectclass: inetOrgPerson
objectclass: organizationalPerson
objectclass: person
objectclass: top
cn: nifiAdmin
description: A nifiAdmin user
sn: nifiAdmin
uid: nifiAdmin
mail: nifiAdmin@love.you
userpassword: password
member: cn=nifiAdmins,ou=groups,dc=love,dc=you
dn: cn=*.love.you,ou=people,dc=love,dc=you
objectClass: person
objectClass: top
cn: *.love.you
sn: *.love.you
Правый клик по созданному разделу и выбрать LDIF Import:
Выберите сохраненный ранее файл и завершите импорт:
Итог импорта:
Об cn=*.love.you
Вы наверняка обратили внимание, что в ou=people после импорта появилось вхождение cn=*.love.you, которое objectClass: person:
Забегая вперед, поясню: это учетная запись для узлов, попадающих под маску сертификата *.love.you. Этой учетке в дальнейшем мы будем давать специальные права для взаимодейтвия с NiFi Registry.
Java Keystore и Java Truststore
Согласно документации, есть два способа передать сертификат и приватный ключ: это с помощью контейнера PKCS12 и с помощью проприетарных контейнеров JKS. Причем, авторы NiFi рекомендуют именно второй.
Потребуется:
Файл сертификата со всей цепочкой в PEM-формате: fullchain.crt;
Файл соответствующего сертификату приватного ключа в PEM-формате: private.key;
Файл сертификата certificate authority (CA) в PEM-формате: cacert.pem;
Как узнать, присутствует ли в сертификате цепочка. Если нет, то как ее сформировать.
Откройте файл на просмотр. Если в нем только один блок:
-----BEGIN CERTIFICATE-----
...
...
...
-----END CERTIFICATE-----
Значит это просто сертификат.
Если блоков два или более, значит вся цепочка.
Для того, чтобы сформировать цепочку, создайте файл, который содержит в себе сначала блок символов (вместе со строками начала и конца) из файла с сертификатом. А после этого блока вставьте блок или блоки из CA сертификата.
Напрямую конвертировать сертификат и ключ в Java Keystore невозможно. Необходимо произвести промежуточную упаковку в контейнер PKCS12:
openssl pkcs12 -export -out nifi.p12 -inkey private.key -in fullchain.crt -name nifi-key
Перед созданием контейнера PKCS12 у вас спросят пароль для последующего экспорта. Сгенерируйте надежный пароль и введите его.
Формируем Java Keystore из PKCS12 контейнера:
keytool -importkeystore -srckeystore nifi.p12 -srcstoretype pkcs12 -srcalias nifi-key -destkeystore keystore.jks -deststoretype jks -destalias nifi-key
Введите пароль для экспорта, который указали на предыдущем шаге. Далее сгенерируйте надежный пароль для самого Java Keystore, введите его.
Формируем Java Truststore:
keytool -importcert -alias nifi-cert -file cacert.pem -keystore truststore.jks
У вас спросят пароль для Java Truststore. Сгенерируйте надежный пароль и введите его. Не возбраняется использовать одинаковый пароль для Keystore и для Truststore. Это снизит вероятность путаницы при дальнейшей настройке. Но тут уж как вы сами договоритесь со своим внутренним параноиком.
Полученные JKS контейнеры скопируйте на серверы с NiFi, где ведется разработка, на продуктовый NiFi и на сервер с NiFi Registry, разместив их по пути /love/conf/cert/;
Для завершения настройки NiFi на сервере, где ведется разработка, отредактируйте файл $NIFI_HOME/config/nifi.properties, приведя значения параметров к виду под спойлером.
nifi.properties
# Site to Site properties
nifi.remote.input.host=nifi-deve.love.you
nifi.remote.input.secure=true
nifi.remote.input.socket.port=10443
# web properties #
nifi.web.http.host=
nifi.web.http.port=
nifi.web.https.host=nifi-deve.love.you
nifi.web.https.port=9443
# security properties #
nifi.security.keystore=/love/conf/cert/keystore.jks
nifi.security.keystoreType=jks
nifi.security.keystorePasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
nifi.security.truststore=/love/conf/cert/truststore.jks
nifi.security.truststoreType=jks
nifi.security.truststorePasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
nifi.security.allow.anonymous.authentication=false
nifi.security.user.login.identity.provider=ldap-provider
Обратите внимание: необходимо удалить значения с параметров nifi.web.http.host и nifi.web.http.port. Если этого не сделать, получите ошибку при запуске и сообщение о том, что NiFi не может быть запущен одновременно на двух портах.
Так же обратите внимание на строку 21 - тут определяется, что будет служить источником учетных записей.Не забудьте заменить пароль
sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
на действительный, сгенерированный вами.
Для завершения настройки NiFi на продуктовом сервере, отредактируйте файл $NIFI_HOME/config/nifi.properties, приведя значения параметров к виду под спойлером.
nifi.properties
# Site to Site properties
nifi.remote.input.host=nifi.love.you
nifi.remote.input.secure=true
nifi.remote.input.socket.port=10443
# web properties #
nifi.web.http.host=
nifi.web.http.port=
nifi.web.https.host=nifi.love.you
nifi.web.https.port=9443
# security properties #
nifi.security.keystore=/love/conf/cert/keystore.jks
nifi.security.keystoreType=jks
nifi.security.keystorePasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
nifi.security.truststore=/love/conf/cert/truststore.jks
nifi.security.truststoreType=jks
nifi.security.truststorePasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
nifi.security.allow.anonymous.authentication=false
nifi.security.user.login.identity.provider=ldap-provider
# Identity Mapping Properties #
nifi.security.identity.mapping.pattern.dn=^CN=(.*?)$
nifi.security.identity.mapping.value.dn=$1
nifi.security.identity.mapping.transform.dn=NONE
Обратите внимание: появились настройки переопределения значений идентификации. Смысл этой настройки я объясню ниже.
Так же обратите внимание на строку 21 - тут определяется, что будет служить источником учетных записей.Не забудьте заменить пароль
sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
на действительный, сгенерированный вами.
Для завершения настройки NiFi Registry, отредактируйте файл $NIFI_REGISTRY_HOME/config/nifi-registry.properties, приведя значения параметров к виду под спойлером.
nifi-registry.properties
# web properties #
nifi.registry.web.http.host=
nifi.registry.web.http.port=
nifi.registry.web.https.host=nifi-re.love.you
nifi.registry.web.https.port=8443
# security properties #
nifi.registry.security.keystore=/abc/conf/cert/keystore.jks
nifi.registry.security.keystoreType=jks
nifi.registry.security.keystorePasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
nifi.registry.security.truststore=/abc/conf/cert/truststore.jks
nifi.registry.security.truststoreType=jks
nifi.registry.security.truststorePasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
nifi.registry.security.needClientAuth=false
nifi.registry.security.identity.provider=ldap-identity-provider
# Identity Mapping Properties #
nifi.registry.security.identity.mapping.pattern.dn=^CN=(.*?)$
nifi.registry.security.identity.mapping.value.dn=$1
nifi.registry.security.identity.mapping.transform.dn=NONE
И вновь хочу обратить внимание: настройки переопределения значений идентификации. Смысл этой настройки я объясню ниже.
Так же обратите внимание на строку 16 - тут определяется, что будет служить источником учетных записей.Не забудьте заменить пароль
sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
на действительный, сгенерированный вами.
Аутентификации через LDAP в NiFi
Для настройки аутентификации через LDAP потребуется отредактировать два файла: $NIFI_HOME/conf/login-identity-providers.xml и $NIFI_HOME/conf/authorizers.xml
В файле login-identity-providers.xml определяется выбор способов входа и их ключевые параметры. Здесь настривается LDAP-подключение и удаляется все остальное. Приведите файл к виду под спойлером.
login-identity-providers.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<loginIdentityProviders>
<provider>
<identifier>ldap-provider</identifier>
<class>org.apache.nifi.ldap.LdapProvider</class>
<property name="Authentication Strategy">SIMPLE</property>
<property name="Manager DN">uid=admin,ou=system</property>
<property name="Manager Password">secret</property>
<property name="TLS - Keystore"></property>
<property name="TLS - Keystore Password"></property>
<property name="TLS - Keystore Type"></property>
<property name="TLS - Truststore"></property>
<property name="TLS - Truststore Password"></property>
<property name="TLS - Truststore Type"></property>
<property name="TLS - Client Auth"></property>
<property name="TLS - Protocol"></property>
<property name="TLS - Shutdown Gracefully"></property>
<property name="Referral Strategy">FOLLOW</property>
<property name="Connect Timeout">10 secs</property>
<property name="Read Timeout">10 secs</property>
<property name="Url">ldap://auth.love.you:10389</property>
<property name="User Search Base">ou=people,dc=love,dc=you</property>
<property name="User Search Filter">(uid={0})</property>
<property name="Identity Strategy">USE_USERNAME</property>
<property name="Authentication Expiration">12 hours</property>
</provider>
</loginIdentityProviders>
Настройки особого интереса не представляют, кроме строк 27 и 29. В 27 строке мы устанавливаем фильтр, который будет использоваться для выборки из результатов, возвращаемым нашим LDAP-сервером. {0} - это заглушка, вместо которой будет подставлено значение поля User формы логина NiFi; uid - атрибут, который назначен учетной записи пользователя и который имеет значение, совпадающее с именем этой учетной записи. Например, nifiUser.
Так же обратите внимание, что значение фильтра взято в круглые скобки. Таков синтаксис ApacheDS.
29 строка - способ идентификации пользователей: либо по имени (USE_USERNAME), либо по DN (USE_DN). Эстетичней выглядит, конечно же, по имени. DN можно использовать для дебага.
В файле authorizers.xml определяются значения параметров, влияющих на способ представления пользователей и групп в NiFi и определяется "нулевой" администратор. Приведите файл к виду под спойлером.
authorizers.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<authorizers>
<userGroupProvider>
<identifier>ldap-user-group-provider</identifier>
<class>org.apache.nifi.ldap.tenants.LdapUserGroupProvider</class>
<property name="Authentication Strategy">SIMPLE</property>
<property name="Manager DN">uid=admin,ou=system</property>
<property name="Manager Password">secret</property>
<property name="TLS - Keystore"></property>
<property name="TLS - Keystore Password"></property>
<property name="TLS - Keystore Type"></property>
<property name="TLS - Truststore"></property>
<property name="TLS - Truststore Password"></property>
<property name="TLS - Truststore Type"></property>
<property name="TLS - Client Auth"></property>
<property name="TLS - Protocol"></property>
<property name="TLS - Shutdown Gracefully"></property>
<property name="Referral Strategy">FOLLOW</property>
<property name="Connect Timeout">10 secs</property>
<property name="Read Timeout">10 secs</property>
<property name="Url">ldap://auth.love.you:10389</property>
<property name="Page Size"></property>
<property name="Sync Interval">1 mins</property>
<property name="Group Membership - Enforce Case Sensitivity">false</property>
<property name="User Search Base">ou=people,dc=love,dc=you</property>
<property name="User Object Class">person</property>
<property name="User Search Scope">ONE_LEVEL</property>
<property name="User Search Filter"></property>
<property name="User Identity Attribute">cn</property>
<property name="User Group Name Attribute">member</property>
<property name="User Group Name Attribute - Referenced Group Attribute"></property>
<property name="Group Search Base">ou=groups,dc=love,dc=you</property>
<property name="Group Object Class">groupOfUniqueNames</property>
<property name="Group Search Scope">ONE_LEVEL</property>
<property name="Group Search Filter"></property>
<property name="Group Name Attribute">cn</property>
<property name="Group Member Attribute"></property>
<property name="Group Member Attribute - Referenced User Attribute"></property>
</userGroupProvider>
<accessPolicyProvider>
<identifier>file-access-policy-provider</identifier>
<class>org.apache.nifi.authorization.FileAccessPolicyProvider</class>
<property name="User Group Provider">ldap-user-group-provider</property>
<property name="Authorizations File">./conf/authorizations.xml</property>
<property name="Initial Admin Identity">nifiAdmin</property>
<property name="Legacy Authorized Users File"></property>
<property name="Node Identity 1"></property>
<property name="Node Group"></property>
</accessPolicyProvider>
<authorizer>
<identifier>managed-authorizer</identifier>
<class>org.apache.nifi.authorization.StandardManagedAuthorizer</class>
<property name="Access Policy Provider">file-access-policy-provider</property>
</authorizer>
</authorizers>
Интерес представляют следующие строки:
31 - определяется значение objectClass в ApacheDS, по которому будут отфильтровываться учетные записи из содержимого каталога;
35 - определяется имя атрибута, по значению которого будет определяться принадлежность пользователя к той или иной группе;
39 - определяется objectClass, по значению которого будут отфильтровываться группы из содержимого каталога;
50 - определятся имя блока, который служит источником учетных записей и групп (тег identifier: <identifier>ldap-user-group-provider</identifier> блока <userGroupProvider>);
52 - имя учетной записи, которая будет иметь администраторские права при первом входе в систему - "нулевой" администратор.
Теперь можно запускать NiFi и входить с учетной записью nifiAdmin и паролем, заданным в ldif-файле.
Аутентификации через LDAP в NiFi Registry
Настройки NiFi Registry повторяют настройки NiFi. Приведите файл $NIFI_REGISTRY_HOME/conf/identity-providers.xml к виду под спойлером.
identity-providers.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<identityProviders>
<provider>
<identifier>ldap-identity-provider</identifier>
<class>org.apache.nifi.registry.security.ldap.LdapIdentityProvider</class>
<property name="Authentication Strategy">SIMPLE</property>
<property name="Manager DN">uid=admin,ou=system</property>
<property name="Manager Password">secret</property>
<property name="Referral Strategy">FOLLOW</property>
<property name="Connect Timeout">10 secs</property>
<property name="Read Timeout">10 secs</property>
<property name="Url">ldap://auth.love.you:10389</property>
<property name="User Search Base">ou=people,dc=love,dc=you</property>
<property name="User Search Filter">(uid={0})</property>
<property name="Identity Strategy">USE_USERNAME</property>
<property name="Authentication Expiration">12 hours</property>
</provider>
</identityProviders>
Приведите файл $NIFI_REGISTRY_HOME/conf/authorizers.xml к виду под спойлером.
authorizers.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<authorizers>
<userGroupProvider>
<identifier>ldap-user-group-provider</identifier>
<class>org.apache.nifi.registry.security.ldap.tenants.LdapUserGroupProvider</class>
<property name="Authentication Strategy">SIMPLE</property>
<property name="Manager DN">uid=admin,ou=system</property>
<property name="Manager Password">secret</property>
<property name="TLS - Keystore"></property>
<property name="TLS - Keystore Password"></property>
<property name="TLS - Keystore Type"></property>
<property name="TLS - Truststore"></property>
<property name="TLS - Truststore Password"></property>
<property name="TLS - Truststore Type"></property>
<property name="TLS - Client Auth"></property>
<property name="TLS - Protocol"></property>
<property name="TLS - Shutdown Gracefully"></property>
<property name="Referral Strategy">FOLLOW</property>
<property name="Connect Timeout">10 secs</property>
<property name="Read Timeout">10 secs</property>
<property name="Url">ldap://auth.love.you:10389</property>
<property name="Page Size"></property>
<property name="Sync Interval">1 mins</property>
<property name="Group Membership - Enforce Case Sensitivity">false</property>
<property name="User Search Base">ou=people,dc=love,dc=you</property>
<property name="User Object Class">person</property>
<property name="User Search Scope">ONE_LEVEL</property>
<property name="User Search Filter"></property>
<property name="User Identity Attribute">cn</property>
<property name="User Group Name Attribute">member</property>
<property name="User Group Name Attribute - Referenced Group Attribute"></property>
<property name="Group Search Base">ou=groups,dc=love,dc=you</property>
<property name="Group Object Class">groupOfUniqueNames</property>
<property name="Group Search Scope">ONE_LEVEL</property>
<property name="Group Search Filter"></property>
<property name="Group Name Attribute">cn</property>
<property name="Group Member Attribute"></property>
<property name="Group Member Attribute - Referenced User Attribute"></property>
</userGroupProvider>
<accessPolicyProvider>
<identifier>file-access-policy-provider</identifier>
<class>org.apache.nifi.registry.security.authorization.file.FileAccessPolicyProvider</class>
<property name="User Group Provider">ldap-user-group-provider</property>
<property name="Authorizations File">./conf/authorizations.xml</property>
<property name="Initial Admin Identity">nifiAdmin</property>
<property name="NiFi Group Name"></property>
</accessPolicyProvider>
<authorizer>
<identifier>managed-authorizer</identifier>
<class>org.apache.nifi.registry.security.authorization.StandardManagedAuthorizer</class>
<property name="Access Policy Provider">file-access-policy-provider</property>
</authorizer>
</authorizers>
Теперь можно запускать NiFi Registry и входить с учетной записью nifiAdmin и паролем, заданным в ldif-файле.
Переопределение значений идентификации
Теперь обещанные пара слов о параметрах в блоке Identity Mapping Properties файлов nifi.properties и nifi-registry.properties.
Собственно, вокруг этого блока и крутится успешная настройка связки NiFi и NiFi Registry.
Как следует из документации по настройке такой связки, необходимо создать пользователя с правами "Proxy user requests". На мой взгляд, такая формулировка вводит в заблуждение, поскольку происходит смешение понятий. Пользователь в том смысле, что это "учетная запись живого человека" смешивается с "учетной записью узла", которой, собственно и нужно давать права на проксирование запросов. На мой взгляд, корректнее было бы говорить не о пользователях, а о сущностях. Но авторы посчитали, что это усложнение концепций на ровном месте. И я в целом с ними согласен. И считаю нужным внести больше ясности в объяснение настройки.
Почему так важно сделать акцент на этом смешении? Причина заключается в том, что при обращении NiFi к NiFi Registry подключение происходит не с учетными данными пользователя, под которым вы вошли в систему. NiFi Registry при обращении к нему NiFi видит сущность, которую NiFi подтянул из Java Keystore и которой, собственно, и представился пред очами NiFi Registry. А, поскольку мы используем wildcard сертификат, то и представился он как CN=*.love.you.
Важная ремарка!
На самом деле, тут следует сделать акцент на важной особенности поведения NiFi в процессах аутентификации. Возможности сравнить у меня не было, но подозреваю, что атрибут CN в сертификате может разниться от издателя к издателю. Причем разниться оформительски. Например, вместо CN может оказаться cn. А NiFi таких вольностей неприемлет.
И с этого момента начинается интересное. ApacheDS атрибут cn пишет прописными буквами. А в сертификате он написан заглавными. Это раз. Второе: при аутентификации используется только значение атрибута. И если зайти в NiFi и посмотреть на список пользователей, то мы увидим три вхождения: nifiUser, nifiAdmin и *.love.you. Без всяких cn=....
И, собственно, для нормализации сущностей, участвующих в аутентификации, и используется механизм переопределения значений.
Исходя из вышесказанного, становится понятно, что в параметре ....mapping.pattern.dn определяется регулярное выражение с capture group, а в параметре ....mapping.value.dn определяется регулярное выражение подменного значения. Иными словами значение CN=*.love.you подменяется значением *.love.you, которое совпадает с учетной записью в ApacheDS.
Настройка связки NiFi и NiFi Registry
Я не стану вдаваться в пошаговые инструкции по захвату прав в NiFi нулевым администратором. Предполагаю, что вы умеете это делать, раз уже вводили NiFi в эксплуатацию. А если нет, то права вам нужно создать и назначить себе в двух местах.
Пиктограмма с ключиком на панели Operate:
И пункт Policies в меню, окрывающемся по нажатии на пиктограмму гамбургера в правом верхнем углу экрана:
Выполнив захват прав для учетной записи нулевого администратора, добавьте пользователя *.love.you в proxy user requests:
Далее перейдите в раздел Controller Settings:
Перейдите на вкладку REGISTRY CLIENTS:
И, нажав на иконку + в правой части экрана, заполните поля, необходимые для подключения:
Перейдите в NiFi Registry, войдите под учетной записью нулевого администратора и откройте настройки, нажав на пиктограмму гаечного ключа в правом верхнем углу:
На вкладке USERS нажмите на пиктограмму карандаша:
И дайте права на проксирование запросов:
На соседней вкладке создайте Bucket и назовите его Test
С этого момента можно включить версионирование в NiFi. Создадим process group и назовем ее Test. Щелкнем правой кнопкой мыши на заголовке созданной process group и выберем Version -> Start version control:
Заполните поля диалогового окна:
По нажатии SAVE в заголовке process group появится зеленая галочка:
Версионирование для этой process group включено.
Трансфер данных из одного NiFi в другой с помощью NiFi Cli
Теперь, когда вы ведете версионирование process group и ваши flow сохраняются в Registry, можно наладить импорт данных в целевой (продуктовый) NiFi.
Скачайте NiFi Toolkit со страницы загрузок NiFi и распакуйте его в удобное вам место на любой удобной вам машине.
Создайте два файла: $NIFI_TOOLKIT_HOME/config/reg.properties и $NIFI_TOOLKIT_HOME/config/nifi-prod.properties:
Настройки для подключения к NiFi Registry:
reg.properties
baseUrl=https://nifi-re.love.you:8443
keystore=/love/conf/cert/keystore.jks
keystoreType=jks
keystorePasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
keyPasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
truststore=/love/conf/cert/truststore.jks
truststoreType=jks
truststorePasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
proxiedEntity=nifiAdmin
Не забудьте заменить пароль
sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
на действительный, сгенерированный вами.
Настройки для подключения к целевому (продуктовому) NiFi:
nifi-prod.properties
baseUrl=https://nifi.love.you:9443
keystore=/love/conf/cert/keystore.jks
keystoreType=jks
keystorePasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
keyPasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
truststore=/love/conf/cert/truststore.jks
truststoreType=jks
truststorePasswd=sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
proxiedEntity=nifiAdmin
Не забудьте заменить пароль
sF9ZCZvX#9rKHQY-Jv1PSx%IXpeGZ4@nwrO
на действительный, сгенерированный вами.
Последовательность действий:
Запрашиваем список бакетов у NiFi Registry и определяем ID бакета, из которого будем забирать flow.
Запрашиваем список flow из бакета с ID из предыдущего шага и определяем ID того flow, который будем перекидывать в целевой (продуктовый) NiFi.
Запрашиваем список версий интересующего flow;
Закидываем flow требуемой версии в целевой (продуктовый) NiFi.
Переходим в $NIFI_TOOLKIT_HOME/bin и поехали:
Запрашиваем список бакетов:
./cli.sh registry list-buckets -p ../conf/reg.properties
Получаем вывод:
# Name Id Description
- ---- ------------------------------------ -----------
1 Test 84744b22-0e2e-4342-b6ab-6658ff0e54ec (empty)
Запрашиваем список flow из бакета 84744b22-0e2e-4342-b6ab-6658ff0e54ec:
./cli.sh registry list-flows -b 84744b22-0e2e-4342-b6ab-6658ff0e54ec -p ../conf/reg.properties
Получаем вывод:
# Name Id Description
- ------------------ ------------------------------------ ------------------
1 PG versioning test bc9a3ff4-2d9c-44b0-bd8e-d86b51d3bac6 PG versioning test
Запрашиваем список версий интересующего flow:
./cli.sh registry list-flow-versions -f bc9a3ff4-2d9c-44b0-bd8e-d86b51d3bac6 -p ../conf/reg.properties
Получаем вывод:
Ver Date Author Message
--- -------------------------- --------- ------------------
1 Thu, Apr 22 2021 09:28 UTC nifiAdmin PG versioning test
Закидываем flow в целевой (продуктовый) NiFi:
./cli.sh nifi pg-import -b 84744b22-0e2e-4342-b6ab-6658ff0e54ec -f bc9a3ff4-2d9c-44b0-bd8e-d86b51d3bac6 -fv 1 -p ../conf/nifi-prod.properties
Получаем вывод:
f90df705-0178-1000-04fe-45ba27e76f99
Вывод - это ID process group в целевом (продуктовом) NiFi:
Вместо заключения
Лукавить не стану, записал этот HowTo в первую очередь для себя по горячим следам. Чтобы раскурить всю последовательность и логику шагов по настройке, пришлось потратить уйму времени, перечитать километры форумов (особенно, когда у меня NiFi не видел список бакетов в Registry), включить режим логирования "TRACE" в NiFi и в NiFi Registry и просканировать еще десятки километров логов. Вот очень не хотелось собирать эту головоломку еще раз, поскольку пройдет месяц и уже и не вспомнишь, что и как делал.
Что касается именно CI/CD, то я не стал рисовать всю цепочку. У каждого свои паттерны и сценарии, да и сам пайплайн был бы оффтопиком. А приведенный пример NiFi Cli, считаю, неплохая отправная точка для реализации собственной схемы доставки.
Спасибо всем, кто дочитал и, надеюсь, текст оказался полезным.
m-pilipenko
Русскоязычные мануалы по NiFi — бесценны. Спасибо!
LazyFao Автор
Приятно слышать. И вам спасибо!