barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)

среда, 17 августа 2016 г.

Spring Security и аутентификация по Active Directory: ошибка "Failed to locate directory entry for authenticated user"

Проблема

Настроил в приложении, использующем Spring Security, аутентификацию по Active Directory (провайдер ActiveDirectoryLdapAuthenticationProvider), но при попытке входа ловлю ошибку:
2016-08-17 11:20:45.525 ERROR 22440 --- [http-nio-8080-exec-154] ctiveDirectoryLdapAuthenticationProvider : Failed to locate directory entry for authenticated user: user@domain.local
javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT), data 0, best match of:
'DC=domain,DC=local'

 ]
at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3160) ~[na:1.8.0_60]
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3081) ~[na:1.8.0_60]
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2888) ~[na:1.8.0_60]
at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1846) ~[na:1.8.0_60]
at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1769) ~[na:1.8.0_60]
at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1786) ~[na:1.8.0_60]
at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:418) ~[na:1.8.0_60]
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:396) ~[na:1.8.0_60]
at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:297) ~[na:1.8.0_60]
at org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleEntryInternal(SpringSecurityLdapTemplate.java:333) ~[spring-security-ldap-4.0.3.RELEASE.jar:4.0.3.RELEASE]
at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.searchForUser(ActiveDirectoryLdapAuthenticationProvider.java:310) ~[spring-security-ldap-4.0.3.RELEASE.jar:4.0.3.RELEASE]
at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.doAuthentication(ActiveDirectoryLdapAuthenticationProvider.java:144) ~[spring-security-ldap-4.0.3.RELEASE.jar:4.0.3.RELEASE]
at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:82) [spring-security-ldap-4.0.3.RELEASE.jar:4.0.3.RELEASE]
Причина

Провайдер ActiveDirectoryLdapAuthenticationProvider работает следующим образом: 
  1. сначала он пытается забиндиться к AD с указанным логином / паролем
  2. после этого ищет объект пользователя по совпадению введенного логина и атрибута userPrincipalName
Попробовал выполнить аналогичный поиск по введенному логину в AD через curl (http://barbitoff.blogspot.ru/2016/08/ldap-ad-ldapsearch.html), поиск не дал результатов. Посмотрел на объект пользователя - он вообще не имеет атрибута userPrincipalName (не большой специалист по AD, поэтому не могу сказать, почему). К счастью, фильтр, используемый для поиска пользователя в ActiveDirectoryLdapAuthenticationProvider кастомизируется путем вызова setSearchFilter().

Как подключиться по LDAP к AD, если под рукой нет ldapsearch

Проблема

Есть AD-сервер, по которому есть следующая информация:
  • IP
  • юзер и пароль
Хочется полазить по нему, но под рукой есть только Linux машина без ldapsearch.

Решение

Зато на машине нашелся curl. Выполняем:
curl -u <user>@<domain>:<password> "ldap://<AD_IP>:389/"
и получаем в выдаче уже кое-какую интересную информацию о сервере. Далее можно выполнять поисковые запросы (см. https://technet.microsoft.com/en-us/library/aa996205(v=exchg.65).aspx) и искать все, что нужно. Например, найти пользователя по логину:
curl -u <user>@<domain>:<password> "ldap://<AD_IP>:389/DC=company,DC=org?memberOf,sAMAccountName?sub?(sAMAccountName=someusr)"
Или посмотреть список всех OU первого уровня:
curl -u <user>@<domain>:<password> "ldap://<AD_IP>:389/DC=company,DC=org?distinguishedName?one?(objectClass=organizationalUnit)" 
По формату используемого LDAP URL можно посмотреть в соотв. RFC: http://www.ietf.org/rfc/rfc2255.txt.

четверг, 11 августа 2016 г.

Spring Security и "javax.naming.PartialResultException [Root exception is javax.naming.CommunicationException: xxx.yyy:389 [Root exception is java.net.UnknownHostException : xxx.yyy]]"

Проблема

Неожиданно в приложении, использующем для аутентификации и авторизации Spring Security + Misrosoft Active Directory, перестала работать аутентификация из-за ошибки:
javax.naming.PartialResultException [Root exception is javax.naming.CommunicationException: xxx.yyy:389 [Root exception is java.net.UnknownHostException: xxx.yyy]]
При этом хостнэйм xxx.yyy не фигурирует в настройках Spring Security (там указан ip сервера AD), единственная корреляция этого хостнэйма с настройками заключается в том, что DC=xxx,DC=yyy - это корневой DN нашего AD.

Решение

Погуглив, нашел, что ошибка PartialResultException говорит о том, что AD-сервер вернул ссылку на вышестоящий AD-лес, и с обработкой этой ссылки возникла какая-то проблема (в нашем случае, ссылка содержит неизвестный хостнэйм xxx.yyy).  Одно из возможных решений - изменить порт, по которому приложение соединяется с AD, с 389 на 3268, по этому порту AD не возвращает ссылок. Спасибо http://stackoverflow.com/questions/16412236/how-to-resolve-javax-naming-partialresultexception.

среда, 3 августа 2016 г.

SLES: пропало место на диске

Проблема

Случилась тут занятная ситуация. На сервере под SLES 11 кончилось место, df показывает, что занято 100% на корневой ФС (всего объем раздела, смонтированного как корневой - более 60Гб). Стали искать, куда же место утекло, смотрим:
du -sh /*
Видим пару папочек по 2-3Гб, остальное - копейки. Суммарно 60Гб совсем не получается, т.е. место вроде бы занято, а чем именно - не понятно.

Решение

Оказалось, в Linux есть интересная особенность, которой нет в Win. Файл может быть удален (т.е. не иметь ни одной ссылки из файловой системы), но при этом продолжать использоваться программами, которые сохранили handle от него, и, соответственно, занимать место на диске. Посмотреть такие файлы можно командой:
lsof +L1
Она как раз покажет файлы, имеющие менее 1 ссылки (т.е. 0 ссылок) в файловой системе. 
В нашем случае это оказались увесистые файлы логов одной из служб, кто-то удалил эти логи, не останавливая службу, и она продолжила их использовать. Решение - останавливаем службу, место на диске магическим образом само расчищается, и секунд через 30 уже имеем 50 свободных гигов.

вторник, 2 августа 2016 г.

SLES: добавление постоянного маршрута

Есть несколько способов, один из них:
  1. Создаем исполняемый файл в /etc/sysconfig/network/if-up.d/. Он будет выполняться при каждом поднятии интерфейса
  2. Прописываем в него команду добавления нужного маршрута, например:
    route add -host 10.1.1.2 gw 192.168.1.100