Вступление

Давайте, я сразу объясню свою баянистость. Да, в интернетах полно мануалов. Да, полно пошаговых прохождений. Да, можете сказать, что все жевано пережевано. Но конкретно в моем случае, как это всегда и бывает, оказалась горстка "но":

Есть мануалы о том, как настроить связку 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 в схожей с гитом манере;

  • Автоматизацию доставки и развертывания релизов с дева на прод.

Наш план:

  1. Настройка Apache DS;

  2. Создание Java Keystore и Java Truststore, включение HTTPS;

  3. Настройка аутентификации через LDAP в NiFi;

  4. Настройка аутентификации через LDAP в NiFi Registry;

  5. Переопределение значений идентификации;

  6. Настройка связки NiFi и NiFi Registry;

  7. Трансфер данных из одного 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 на действительный, сгенерированный вами.

Последовательность действий:

  1. Запрашиваем список бакетов у NiFi Registry и определяем ID бакета, из которого будем забирать flow.

  2. Запрашиваем список flow из бакета с ID из предыдущего шага и определяем ID того flow, который будем перекидывать в целевой (продуктовый) NiFi.

  3. Запрашиваем список версий интересующего flow;

  4. Закидываем 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, считаю, неплохая отправная точка для реализации собственной схемы доставки.

Спасибо всем, кто дочитал и, надеюсь, текст оказался полезным.