Ошибка при входе с использванием LDAP Addon

Добрый день.
После установки и настройки ldap addon (1.5.1) на платформу (7.2.4) начал получать ошибки авторизации, при первом входе пользователя через ldap. При детальном разборе выяснилась проблема - при создании маппинга пользователя и роли работал неправильный индекс и получал ORA-000001 - проблему с уникальностью по индексу. Решил эту проблему как было указано в обсуждении


Но появилась другая проблема - при повторном входе пользователя получаю ORA-000001 уже по таблице SEC_ROLE. Проблема, насколько я понимаю, в том, что аддон пытается создать повторно роль с именем Default LDAP Role, и падает. Это проблема в аддоне? Или, возможно, неправильно сконфигурированы правила ldap (сейчас используется настройка по умолчанию)?

Здравствуйте @sss.slayer,

Аддон не должен создавать новые роли, попробуем разобраться в чем проблема

Здравствуйте,

Отправьте пожалуйста нам какие настройки правил вы используете в LDAP аддоне (LDAP Matching rules) и значение свойства приложения cuba.security.rolesPolicyVersion

С уважением,
Евгений

Прошу прощения за долгий ответ.
rolesPolicyVersion по умолчанию (то есть 2).
Правила такие:

#,ID,VERSION,CREATE_TS,CREATED_BY,UPDATE_TS,UPDATED_BY,DELETE_TS,DELETED_BY,RULE_TYPE,MATCHING_RULE_STATUS_ID,MATCHING_RULE_ORDER_ID,DESCRIPTION,ACCESS_GROUP_ID,ROLES_LIST,IS_TERMINAL_RULE,IS_OVERRIDE_EXISTING_ROLES,IS_OVERRIDE_EXIST_ACCESS_GRP,STRING_CONDITION
1,ff2ebe743836465b918560141a6a0548,2,2020-05-27 01:33:21.000000,admin,2020-07-15 12:41:22.676000,admin,,,DEFAULT,ff2ebe743836465b918560141a6a0548,ff2ebe743836465b918560141a6a0548,Default rule,0fa2b1a51d684d699fbddff348347f93,Default LDAP role,0,0,0,

Возможно проблема в том, что нельзя указывать в правилах “Default LDAP role”?
Получаю ошибку из вложения.strace.txt (31.3 КБ)

Попробуйте переименовать или удалить эту роль и в правилах вместо нее использовать предустановленную Default LDAP role роль

Интересно, что если так сделать то в первый раз вход происходит успешно, но при этом создается роль

ID,CREATE_TS,CREATED_BY,VERSION,UPDATE_TS,UPDATED_BY,DELETE_TS,DELETED_BY,SYS_TENANT_ID,NAME,LOC_NAME,DESCRIPTION,IS_DEFAULT_ROLE,ROLE_TYPE,SECURITY_SCOPE
3aa241256bdd6af46acb3022717cfc5f,2020-07-15 15:39:43.330000,anonymous,1,2020-07-15 15:39:43.330000,,,,,Default LDAP role,,,0,,GENERIC_UI

И при следующем входе ошибка с уникальным constraint’ом.

java.lang.RuntimeException: Error during LDAP synchronization: test_login
	at com.haulmont.addon.ldap.core.service.UserSynchronizationServiceBean.synchronizeUser(UserSynchronizationServiceBean.java:149) ~[ldap-core-1.5.1.jar:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:90) ~[cuba-core-7.2.4.jar:7.2.4]
	at jdk.internal.reflect.GeneratedMethodAccessor177.invoke(Unknown Source) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at com.sun.proxy.$Proxy326.synchronizeUser(Unknown Source) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at com.haulmont.cuba.core.sys.remoting.LocalServiceInvokerImpl.invoke(LocalServiceInvokerImpl.java:94) ~[cuba-core-7.2.4.jar:7.2.4]
	at com.haulmont.cuba.web.sys.remoting.LocalServiceProxy$LocalServiceInvocationHandler.invoke(LocalServiceProxy.java:159) ~[na:na]
	at com.sun.proxy.$Proxy67.synchronizeUser(Unknown Source) ~[na:na]
	at com.haulmont.addon.ldap.web.security.ldapcomponent.LdapAddonLoginProvider.login(LdapAddonLoginProvider.java:97) ~[na:na]
	at com.haulmont.cuba.web.security.ConnectionImpl.loginInternal(ConnectionImpl.java:192) ~[na:na]
	at com.haulmont.cuba.web.security.ConnectionImpl.login(ConnectionImpl.java:91) ~[na:na]
	at com.haulmont.cuba.web.security.LoginScreenAuthDelegate.doLogin(LoginScreenAuthDelegate.java:148) ~[na:na]
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.3.6-cuba): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: нарушено ограничение уникальности (IDX_SEC_ROLE_UNIQ_NAME)

Error Code: 1
Call: INSERT INTO SEC_ROLE (ID, CREATE_TS, CREATED_BY, IS_DEFAULT_ROLE, DELETE_TS, DELETED_BY, DESCRIPTION, LOC_NAME, NAME, SECURITY_SCOPE, SYS_TENANT_ID, ROLE_TYPE, UPDATE_TS, UPDATED_BY, VERSION) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
	bind => [ece1eeec5c596b27638b847b7b4ed58c, 2020-07-15 15:39:53.19, anonymous, false, null, null, , , Default LDAP role, GENERIC_UI, null, null, 2020-07-15 15:39:53.19, null, 1]
Query: InsertObjectQuery(com.haulmont.cuba.security.entity.Role-ece1eeec-5c59-6b27-638b-847b7b4ed58c [managed])
	at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:979) ~[org.eclipse.persistence.jpa-2.7.3-6-cuba.jar:na]

Хотя если создать отдельную роль с именем к примеру Domain Users и сделать правило с ней то пользователь входит успешно и при повторном логине также не проиходит ошибки.

Кажется проблема в том, что аддон пытается создать роль с тем же именем что и встроенная роль, как если бы этой роли не было. Вопрос - а правильно ли я использую эту роль “Default LDAP Role”? Может её нельзя использовать в правилах?

Попробовал создать роль с помощью AnnotatedRoleDefinition, и поменял правило - указал его. Такая же ситуация - при первом входе создается роль в SEC_ROLE, при повторном нарушение констрейнта на SEC_ROLE.

Судя по всему, проблема в том, что когда происходит синхронизация, мы получаем роли из правила
List matchingRules = orElseGet(cachedMatchingRules, matchingRuleDao::getMatchingRules);

При этом в правиле роли записаны в виде строки с конкатенацией. И после загрузки правила они превращаются в объекты ролей:
setRoles(getRolesList() != null ? Arrays.stream(getRolesList().split(";"))
.filter(Objects::nonNull)
.map(String::trim)
.distinct()
.filter(s -> !s.isEmpty())
.map(s -> {
Role role = AppBeans.get(RolesService.class).getRoleDefinitionAndTransformToRole(s);
if (role == null) {
LoadContext roleLoadContext = new LoadContext<>(Role.class);
roleLoadContext
.setView(View.LOCAL)
.setQueryString(“select r from sec$Role r where r.name=:name”)
.setParameter(“name”, s)
.setMaxResults(1);
role = AppBeans.get(DataManager.class).load(roleLoadContext);
}
return role;
}
)
.filter(Objects::nonNull)
.collect(Collectors.toList())
: new ArrayList<>()

AppBeans.get(RolesService.class).getRoleDefinitionAndTransformToRole(s); - возвращает сущность роль в состоянии Detached. И далее во время применения это правило попадает в контекст для сохранения в БД. Таким образом оно каждый раз персистится, а так как getRoleDefinitionAndTransformToRole(s) всегда возвращает разные инстансы мы получаем повторные сохранения одного и того же.
Для не predefined ролей (которые в БД лежат) похоже все нормально.

Спасибо за ваш ответ, мы пробуем воспроизвести и исправить эту ошибку

Здравствуйте, мы нашли в чем была проблема, и постараемся выпустить обновление как можно скорее. Тикет на Github https://github.com/cuba-platform/ldap-addon/issues/93

Здравствуйте @sss.slayer,

Мы исправили эту проблему в версии 1.5.2

Здравствуйте.
Спасибо за ответ, и за быстрое исправление.