Ошибка в Spring Security Kerberos для проверки подлинности Windows

Я пытаюсь настроить веб-приложение безопасности на основе Spring в нашей среде. Как описано в http://docs.spring.io/spring-security-kerberos/docs/1.0.1.RELEASE/reference/htmlsingle/

Чтобы убедиться, что все настроено правильно, я пытаюсь запустить пример приложения Spring Boot Security (созданный, как описано здесь: http://docs.spring.io/spring-security-kerberos/docs/1.0.1.RELEASE/reference/htmlsingle/)

Вот наша тестовая среда в домене TEST:

Контроллер домена Active Directory (называемый сервером AD), 64-разрядная версия Windows 2008 R2
Имя компьютера: adjavatest1
Полное имя компьютера: adjavatest1.test.company.info
Пользователь: TEST\administrator

Клиентский ПК, Windows 7
Имя компьютера: adjavatest2
Полное имя компьютера: adjavatest2.test.company.info
Пользователь: TEST\administrator

Сервер приложений (называемый веб-сервером)
Имя компьютера: kpiq-dev
Полное имя компьютера: kpiq-dev.test.company.info
Пользователь: TEST\administrator

До сих пор я сделал следующие шаги для настройки среды и приложения

1) установить SPN на сервере AD

setspn -A HTTP/adjavatest1.test.company.info TEST\administrator

(многие источники советуют создавать SPN "HTTP/adjavatest1" и "HOST/adjavatest1" - я пробую это без разницы.)

2) проверить SPN на сервере AD

>setspn -L TEST\administrator
Registered ServicePrincipalNames for CN=Administrator,CN=Users,DC=test,DC=company,DC=info:
HTTP/adjavatest1.test.company.info

3) Сопоставьте пользователя / службу и сгенерируйте файл keytab на сервере AD.

>ktpass -princ HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO -pass pswd123 -mapuser TEST\Administrator -out .\ adjavatest1.HTTP.keytab -ptype KRB5_NT_PRINCIPAL -crypto All
Targeting domain controller:  adjavatest1.test.company.info
Using legacy password setting method
Successfully mapped HTTP/adjavatest1.test.company.info to Administrator.
Key created.
Key created.
Key created.
Key created.
Key created.
Output keytab to .\ adjavatest1.HTTP.keytab:
Keytab version: 0x502
keysize 85 HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO ptype 1 (KRB5_NT_PRINCIPAL) vno 5 etype 0x1 (DES-CBC-CRC) keylength 8 (0x6da81379831f37ad)
keysize 85 HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO ptype 1 (KRB5_NT_PRINCIPAL) vno 5 etype 0x3 (DES-CBC-MD5) keylength 8 (0x6da81379831f37ad)
keysize 93 HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO ptype 1 (KRB5_NT_PRINCIPAL) vno 5 etype 0x17 (RC4-HMAC ) keylength 16 (0xe32edb70a8df744e3b0f87ea7ff515f7)
keysize 109 HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO ptype 1 (KRB5_NT_PRINCIPAL) vno 5 etype 0x12 (AES256-SHA1) keylength 32 (0xf744e212c2e48e34c815364c0b5290a68b37b6c65a7cd0befcbcc2625e3e6c79)
keysize 93 HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO ptype 1 (KRB5_NT_PRINCIPAL) vno 5 etype 0x11 (AES128-SHA1) keylength 16 (0x20f3474a818d4d326136449a8a660e2c)

4) скопировать файл keytab на веб-сервер в каталоге C;\SpringSSO

5) Проверить keytab на веб-сервере
С помощью инструмента kinit из MIT kerberos c:\SpringSSO>kinit -V -k -t adjavatest1.HTTP.keytab HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO Использование существующего кэша: исходный ccache по умолчанию Использование принципала: HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO Использование keytab: adjavatest1.HTTP.keytab Аутентифицировано в Kerberos v5 С помощью kinit из jdk c:\SpringSSO>kinit -k -t adjavatest1.HTTP.keytab HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO Новый тикет хранится в кеш-файле C: \ Users \ administrator.TEST \ krb5cc_administrator

6) Установите "Kerberos и Политика неограниченной силы" в jre/lib/security на веб-сервере в обоих местах:

c:\Program Files\Java\jre1.8.0_65\lib\security\
c:\Program Files\Java\jdk1.8.0_65\jre\lib\security\

7) Проверьте реестр Windows на веб-сервере:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\
Value Name: allowtgtsessionkey
Value: 0x1

8) создать приложение spring-security-kerberos-samples\sec-server-win-auth, взятое с https://github.com/spring-projects/spring-security-kerberos/tree/master/spring-security-kerberos-samples со свойствами конфигурации в application.yml

server:
    port: 80
app:
    ad-domain: TEST.COMPANY.INFO
    ad-server: ldap://ADJAVATEST1.TEST.COMPANY.INFO/
    service-principal: HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO
    keytab-location:  adjavatest1.HTTP.keytab
    ldap-search-base: DC=TEST,DC=COMPANY,DC=INFO
    ldap-search-filter: "(| (userPrincipalName={0}) (sAMAccountName={0}))"

9) развернуть загрузочное приложение Spring на веб-сервере в каталоге C:\SpringSSO

10) Запустите веб-приложение на веб-сервере c:\SpringSSO>java -Dsun.security.krb5.debug=true -Djava.security.krb5.conf=.\ Krb5.conf -jar sec-server-win-auth-1.0.2.BUILD-SNAPSHOT.jar

Конфигурация Kerberos в krb5.conf (я пробовал разные энктипы, и "arcfour-hmac-md5" - это только последний эксперимент)

[libdefaults]
 default_realm = TEST.COMPANY.INFO
 permitted_enctypes = arcfour-hmac-md5 rc4-hmac aes256-cts aes128-cts des3-cbc-sha1 des-cbc-md5 des-cbc-crc
 default_tgs_enctypes = arcfour-hmac-md5 rc4-hmac aes256-cts aes128-cts des3-cbc-sha1 des-cbc-md5 des-cbc-crc
 default_tkt_enctypes = arcfour-hmac-md5 rc4-hmac aes256-cts aes128-cts des3-cbc-sha1 des-cbc-md5 des-cbc-crc
 dns_lookup_kdc = true
 dns_lookup_realm = false

[realms]
 TEST.COMPANY.INFO = {
     kdc =  ADJAVATEST1.TEST.COMPANY.INFO
     admin_server =  ADJAVATEST1.TEST.COMPANY.INFO
     master_kdc =  ADJAVATEST1.TEST.COMPANY.INFO
     default_domain = TEST.COMPANY.INFO
 }

[domain_realm]
 .TEST.COMPANY.INFO = TEST.COMPANY.INFO
 TEST.COMPANY.INFO = TEST.COMPANY.INFO

11) В браузере IE на клиенте добавьте путь *.test.company.info к браузеру IE в качестве браузера точки шаблона интрасети к http: // kpiq-dev.test.company.info/hello

12) Направьте браузер на http: // kpiq-dev.test.company.info/hello

13) Проверьте журнал на веб-сервере, указывая, что сервер не может кодировать

2015-12-17 08:55:35.893 DEBUG 1876 --- [p-nio-80-exec-3] w.a.SpnegoAuthenticationProcessingFilter : Received Negotiate Header for request http:// kpiq-dev.test.company.info/hello: Negotiate YIIH ...trucated... H4qgvsM
2015-12-17 08:55:35.893 DEBUG 1876 --- [p-nio-80-exec-3] o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider
2015-12-17 08:55:35.893 DEBUG 1876 --- [p-nio-80-exec-3] .a.KerberosServiceAuthenticationProvider : Try to validate Kerberos Token
Found KeyTab c:\SpringSSO\ adjavatest1.HTTP.keytab for HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO
Found KeyTab c:\SpringSSO\ adjavatest1.HTTP.keytab for HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO
Entered Krb5Context.acceptSecContext with state=STATE_NEW
Java config name: .\krb5.conf
Loaded from Java config
>>> KeyTabInputStream, readName(): TEST.COMPANY.INFO
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName():  adjavatest1.test.company.info
>>> KeyTab: load() entry length: 85; type: 1
>>> KeyTabInputStream, readName(): TEST.COMPANY.INFO
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName():  adjavatest1.test.company.info
>>> KeyTab: load() entry length: 85; type: 3
>>> KeyTabInputStream, readName(): TEST.COMPANY.INFO
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName():  adjavatest1.test.company.info
>>> KeyTab: load() entry length: 93; type: 23
>>> KeyTabInputStream, readName(): TEST.COMPANY.INFO
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName():  adjavatest1.test.company.info
>>> KeyTab: load() entry length: 109; type: 18
>>> KeyTabInputStream, readName(): TEST.COMPANY.INFO
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName():  adjavatest1.test.company.info
>>> KeyTab: load() entry length: 93; type: 17
Looking for keys for: HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO
Added key: 17version: 5
Added key: 18version: 5
Added key: 23version: 5
Found unsupported keytype (3) for HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO
Found unsupported keytype (1) for HTTP/adjavatest1.test.company.info@TEST.COMPANY.INFO
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
2015-12-17 08:55:36.236  WARN 1876 --- [p-nio-80-exec-3] w.a.SpnegoAuthenticationProcessingFilter : Negotiate Header was invalid: Negotiate YIIHNAYGKwYBBQU ...trucated... dH4qgvsM

org.springframework.security.authentication.BadCredentialsException: Kerberos validation not successful
            at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:71)
            at org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:64)
            at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
            at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:177)
            at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:446)
            at org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:145)
            at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
...trucated...
            at java.lang.Thread.run(Unknown Source)
Caused by: java.security.PrivilegedActionException: null
            at java.security.AccessController.doPrivileged(Native Method)
            at javax.security.auth.Subject.doAs(Unknown Source)
            at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:68)
            ... 45 common frames omitted
Caused by: org.ietf.jgss.GSSException: Failure unspecified at GSS-API level (Mechanism level: Checksum failed)
            at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Unknown Source)
            at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
            at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
            at sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(Unknown Source)
            at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(Unknown Source)
            at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
            at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
            at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:170)
            at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:153)
            ... 48 common frames omitted
Caused by: sun.security.krb5.KrbCryptoException: Checksum failed
            at sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType.decrypt(Unknown Source)
            at sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType.decrypt(Unknown Source)
            at sun.security.krb5.EncryptedData.decrypt(Unknown Source)
            at sun.security.krb5.KrbApReq.authenticate(Unknown Source)
            at sun.security.krb5.KrbApReq.<init>(Unknown Source)
            at sun.security.jgss.krb5.InitSecContextToken.<init>(Unknown Source)
            ... 57 common frames omitted
Caused by: java.security.GeneralSecurityException: Checksum failed
            at sun.security.krb5.internal.crypto.dk.AesDkCrypto.decryptCTS(Unknown Source)
            at sun.security.krb5.internal.crypto.dk.AesDkCrypto.decrypt(Unknown Source)
            at sun.security.krb5.internal.crypto.Aes256.decrypt(Unknown Source)
            ... 63 common frames omitted

Зачем безопасности пытаться кодировать Aes256CtsHmacSha1EType вместо rc4-hmac?
Любое предложение, что я могу попробовать дальше?

Заранее спасибо.

2 ответа

Причиной сбоя является то, что в средстве проверки билетов вы пытаетесь проверить токен NTLM, а не билет Kerberos. Эта строка показывает вам это в вашем журнале:

>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType 2015-12-17 08:55:36.236 WARN 1876 --- [p-nio-80-exec-3] w.a.SpnegoAuthenticationProcessingFilter : Negotiate Header was invalid: Negotiate YIIHNAYGKwYBBQU ...trucated... dH4qgvsM

Заголовки, начинающиеся с YII, обозначают NTLM, что означает, что при первоначальной проверке не удается получить билет Kerberos, поэтому браузер пробует следующий протокол в порядке приоритета, в данном случае NTLM.

Похоже, что ваш SPN правильный, есть некоторые вещи, которые я бы посоветовал проверить в отношении учетной записи и файла keytab. Убедитесь, что учетная запись пользователя, которую вы сопоставляете с именем участника-службы и используете для создания таблицы ключей, имеет правильные параметры, выбранные в управлении пользователями активного каталога, то есть разрешить 126- и 256-битное шифрование с помощью Kerberos и разрешить учетной записи использоваться для делегирования Kerberos.

Кроме того, эту ссылку важно прочитать: https://www.chromium.org/developers/design-documents/http-authentication

Эта ссылка описывает, как Chrome создает SPN из URL-адреса запроса для выполнения SPNEGO/SSO. По сути, возможно, вам придется настроить зону пересылки в DNS, чтобы решить проблему, с которой вы столкнулись. Браузер Chrome получает настройки из IE, поэтому настройка параметров интрасети в IE должна с этим справиться, но в отношении разрешения SPN он попытается разрешить значение в URL для CNAME, а затем для записи A в DNS. Это может вызвать поведение, которое вы видите. Обычно, когда вы видите токен NTLM, отправленный вместо билета Kerberos, он может быть прослежен браузером, пытающимся использовать неправильный SPN для запроса и получения билета Kerberos. Если вы можете настроить SPN, созданный в браузере, на синхронизацию с тем, который вы сопоставляете с учетной записью службы, которую вы используете, у вас все получится.

Две возможные ошибки:

1) krb5.conf неправильно загружен

2) Принципал службы не настроен должным образом

Решение для 1-го:

  • в пункте 8) добавьте приложение: kerberos-conf: /home/xyz/krb5.conf в application.yaml
  • создать дополнительный класс в весеннем проекте безопасности

        @Configuration
        public class KerberosGlobalConfig {
    
            @Value("${app.kerberos-conf}")
            private String kerberosGlobalConfPath;
    
            @Bean
            public GlobalSunJaasKerberosConfig globalSunJaasKerberosConfig() {
                GlobalSunJaasKerberosConfig globalSunJaasKerberosConfig = new 
                GlobalSunJaasKerberosConfig();
                //TODO remove hardcoding
                globalSunJaasKerberosConfig.setDebug(true);
                globalSunJaasKerberosConfig.setKrbConfLocation(kerberosGlobalConfPath);
                return globalSunJaasKerberosConfig;
            }
    
        } 
    
Другие вопросы по тегам