How to configure kerberos on Tomcat/linux server?
Asked Answered
Z

2

2

I'm trying to setup kerberos authentication in a Java web-app running in a Tomcat on Linux. I'm using the spring security kerberos extension. I'm using:

  • jdk 1.7u75
  • spring-security-kerberos 1.0.0.RELEASE
  • MS Active Directory

On my local development machine (windows) everything runs fine. But after deploying the app to a linux machine authentication is no longer working. I strongly suspect that something is wrong with my Kerberos configuration :

[libdefaults]
  default_realm = INT.MYCOMPANY.DE
  ccache_type=4
  kdc_tymesync=1
  forwardable=true
  proxiable=true

[realms]
  INT.MYCOMPANY.DE = {
   admin_server = xyz.mycompany.de
   kdc = xyz.mycompany.de
   }

[domain_realm]
.INT.MYCOMPANY.DE = INT.MYCOMPANY.DE
int.mycompany.de = INT.MYCOMPANY.DE
.int.mycompany.de = INT.MYCOMPANY.DE
.mycompany.de = INT.MYCOMPANY.DE
mycompany.de = INT.MYCOMPANY.DE

[logging]
#kdc = console

(server and realm name changed)

Spring security config:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="file:${externalPropertiesPath}/edlgui.properties" />

    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="kerberosAuthenticationProvider" />
    </authentication-manager>

    <http use-expressions="true">
        <intercept-url pattern="/login.jsp" access="permitAll" />
        <intercept-url pattern="/admin/**" access="hasRole('${edl.gui.authorization.requiredrole}')" />
        <form-login login-page="/login.jsp" username-parameter="username" password-parameter="password" default-target-url="/admin"/>
        <logout logout-url="/logout" logout-success-url="/login.jsp" />
        <http-basic />
        <access-denied-handler ref="edlGuiAccessDeniedHandler"/>
    </http>

    <beans:bean id="edlGuiAccessDeniedHandler" class="edl.security.EdlGuiAccessDeniedHandler">
        <beans:constructor-arg value="/login.jsp"/>
    </beans:bean>

    <beans:bean id="kerberosAuthenticationProvider" class="org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider">
        <beans:property name="kerberosClient">
            <beans:bean class="org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient">
                <beans:property name="debug" value="false" />
            </beans:bean>
        </beans:property>
        <!-- TODO replace dummy user service -->
        <beans:property name="userDetailsService" ref="ldapUserDetailsService" />
    </beans:bean>

    <beans:bean class="org.springframework.security.kerberos.authentication.sun.GlobalSunJaasKerberosConfig">
        <beans:property name="debug" value="false" />
        <!-- externalPropertiesPath path = /opt/pksvc/tomcat/current/conf -->
        <beans:property name="krbConfLocation" value="file:${externalPropertiesPath}/krb5.conf"/>
    </beans:bean>

    <!-- Get User Details via LDAP -->
    <!-- It would be nice to do this via Kerberos, however that requires a keytab -->
    <ldap-user-service id="ldapUserDetailsService"
        server-ref="activeDirectoryLdap"
        user-search-base="${edl.gui.ldap.usersearchbase}"
        user-search-filter="${edl.gui.ldap.usersearchfilter}"
        group-search-base="${edl.gui.ldap.groupsearchbase}"
        group-role-attribute="${edl.gui.ldap.grouproleattribute}"
        group-search-filter="${edl.gui.ldap.groupsearchfilter}"
        user-details-class="person"/>
    <ldap-server id="activeDirectoryLdap"
        url="${edl.gui.ldap.url}"
        manager-dn="${edl.gui.ldap.managerdn}"
        manager-password="${edl.gui.ldap.managerpw}"
        root="${edl.gui.ldap.root}"/>

</beans:beans>

When I try to login the only thing I see from the kerberos debug output is:

Java config name: file:/opt/pksvc/tomcat/current/conf/krb5.conf
getRealmFromDNS: trying mycompany.de

(I would expect to see 'KrbAsReq creating message' and 'KrbKdcReq send' entries)

And from spring:

2015-08-04 10:07:42.986 DEBUG o.s.security.web.FilterChainProxy - /j_spring_security_check at position 1 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2015-08-04 10:07:42.986 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
2015-08-04 10:07:42.986 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@64656737. A new one will be created.
2015-08-04 10:07:42.986 DEBUG o.s.security.web.FilterChainProxy - /j_spring_security_check at position 2 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2015-08-04 10:07:42.986 DEBUG o.s.security.web.FilterChainProxy - /j_spring_security_check at position 3 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2015-08-04 10:07:42.987 DEBUG o.s.security.web.FilterChainProxy - /j_spring_security_check at position 4 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2015-08-04 10:07:42.987 DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Request is to process authentication
2015-08-04 10:07:42.987 DEBUG o.s.s.authentication.ProviderManager - Authentication attempt using org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider
2015-08-04 10:07:42.987 DEBUG o.s.s.k.a.sun.SunJaasKerberosClient - Trying to authenticate KieselGun with Kerberos
2015-08-04 10:07:42.993 DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Kerberos authentication failed
2015-08-04 10:07:42.993 DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Updated SecurityContextHolder to contain null Authentication
2015-08-04 10:07:42.993 DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Delegating to authentication failure handler org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@72f106b0
2015-08-04 10:07:42.993 DEBUG o.s.s.w.a.SimpleUrlAuthenticationFailureHandler - Redirecting to /login.jsp
2015-08-04 10:07:42.993 DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to '/edl-gui/login.jsp'
2015-08-04 10:07:42.993 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2015-08-04 10:07:42.994 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2015-08-04 10:07:43.042 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 1 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2015-08-04 10:07:43.043 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
2015-08-04 10:07:43.043 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@64656737. A new one will be created.
2015-08-04 10:07:43.043 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 2 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2015-08-04 10:07:43.043 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 3 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2015-08-04 10:07:43.043 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 4 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2015-08-04 10:07:43.043 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2015-08-04 10:07:43.043 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2015-08-04 10:07:43.044 DEBUG o.s.s.w.s.DefaultSavedRequest - pathInfo: both null (property equals)
2015-08-04 10:07:43.044 DEBUG o.s.s.w.s.DefaultSavedRequest - queryString: both null (property equals)
2015-08-04 10:07:43.044 DEBUG o.s.s.w.s.DefaultSavedRequest - requestURI: arg1=/edl-gui/admin; arg2=/edl-gui/login.jsp (property not equals)
2015-08-04 10:07:43.044 DEBUG o.s.s.w.s.HttpSessionRequestCache - saved request doesn't match
2015-08-04 10:07:43.044 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2015-08-04 10:07:43.044 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2015-08-04 10:07:43.044 DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@6faa3d44: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: 172.20.65.226; SessionId: F2C563CA5780A3024AE7D89390CE0AB1; Granted Authorities: ROLE_ANONYMOUS'
2015-08-04 10:07:43.044 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2015-08-04 10:07:43.044 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2015-08-04 10:07:43.045 DEBUG o.s.security.web.FilterChainProxy - /login.jsp at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2015-08-04 10:07:43.045 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login.jsp'; against '/login.jsp'
2015-08-04 10:07:43.045 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /login.jsp; Attributes: [permitAll]
2015-08-04 10:07:43.045 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@6faa3d44: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: 172.20.65.226; SessionId: F2C563CA5780A3024AE7D89390CE0AB1; Granted Authorities: ROLE_ANONYMOUS
2015-08-04 10:07:43.045 DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@265c45f7, returned: 1
2015-08-04 10:07:43.045 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful
2015-08-04 10:07:43.045 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object
2015-08-04 10:07:43.045 DEBUG o.s.security.web.FilterChainProxy - /login.jsp reached end of additional filter chain; proceeding with original chain
2015-08-04 10:07:43.046 DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
2015-08-04 10:07:43.046 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2015-08-04 10:07:43.046 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed

So it seems the user gets authenticated as anonymous, after which I get back to the login page since anonymous users have no access.

Can anyone tell me what's wrong with my configuration? Or how I could further analyse this?

Zulemazullo answered 4/8, 2015 at 8:36 Comment(10)
Please post the security configuration also.Jauch
Added to orginal post.Zulemazullo
If I change the debug flags in the spring config to true I see: getRealmFromDNS: trying int.hlg.de [Krb5LoginModule] authentication failed Cannot locate default realmZulemazullo
Can I be sure from the log output Java config name: file:/opt/pksvc/tomcat/current/conf/krb5.confthat this file is really used?Zulemazullo
try file:///opt/pksvc/tomcat/current/conf/krb5.confJauch
same result: Java config name: file:///opt/pksvc/tomcat_edl/current/conf/krb5.conf getRealmFromDNS: trying mycompany.de [Krb5LoginModule] authentication failed Cannot locate default realm Zulemazullo
Yes, these are very difficult to debug. You could add more info to the question, spring-security-kerberos version(1.0.0 or 1.0.1), is this against win AD(if so how did you create a service user), which jdk version you're using(i.e. bugs in jdk8 github.com/spring-projects/spring-security-kerberos/issues/34). Add -Dsun.security.krb5.debug=true to get more internal jdk debug logging.Mange
Thanks for the hints! -Dsun.security.krb5.debug=true is already set (that's giving me the little output I have). I'll add the other info above.Zulemazullo
Above you asked how the service user was created - indeed I did not use any service user / keytab in this setup. It worked without on my (windows) development machine. Is a service user required here? Sofar I was under the impression I don't need one... (only if I would want to fetch user details or use SpNego).Zulemazullo
Technically you're right yes. Some of the samples are indeed just using passed credentials to check if those can be used to login via kerberos, then i.e. dummy user service(you use ldapUserDetailsService instead) is used to add user to spring sec context. However this is where it gets tricky, if your dev win machine is part of AD domain, you may already have a valid kerberos TGT in local cache and jdk may try to use that. Think I need to try some of these scenarios in my local vm's.Mange
M
1

I'm not sure how jdk's krb implementation differ between linux and win. Obviously there are some differences because in linux jdk will try to find default /etc/krb5.conf and there is one other default location I don't remember right now. I assume in win similar tweaks are in place for jdk. You could event temporarily rename default krb5.conf file to be sure it's not used(and getting wrong config).

I'm shooting in dark here but let's make a random guess. I had a lot of various type of troubles when I make all those samples but eventually got all working. At some point(in linux) when I was totally lost if failures was caused by our spring-security-kerberos libs or something to do with a kerberos settings, etc, I found it to very valuable to test kerberos settings outside of a jdk. See http://docs.spring.io/spring-security-kerberos/docs/1.0.1.RELEASE/reference/htmlsingle/#troubleshooting and especially trying to connect ldapsearch from linux into AD. You don't need to use keytabs because kinit should allow you to get ticket from AD if settings are right.

One thing I have there is:

[realms]
EXAMPLE.ORG = {
  kdc = WIN-EKBO0EQ7TS7.example.org:88
}

I believe I had this port 88 for a reason and maybe there are some different defaults linux/win jdk's if none are defined.

Other think is supported enctypes if those are different used by AD and what linux jdk support. This is something you should see from jdk internal krb debug logs. Also if you are able to kinit against AD from linux, klist will then show key enctypes.

Mange answered 5/8, 2015 at 8:33 Comment(0)
Z
0

I found out that in both my local environment on windows and the linux environment the krb5.conf specified in the GlobalSunJaasKerberosConfig krbConfLocation (see below) was not used. Although the debug output showed this file the changes made there had no effect. In my windows environment I had a correctly setup kerberos configuration (I still don't know where that is, I don't have a krb5.ini anywhere...) in the linux environment I did not. As a result kerberos failed in the linux environment.

I managed to workaround this by setting the environment variables java.security.krb5.realm and java.security.krb5.kdc (see https://blogs.oracle.com/wangwj/entry/kerberos_programming_on_windows). With these set kerberos authentication worked.

The krbConfLocation from this bean was not used:

<beans:bean class="org.springframework.security.kerberos.authentication.sun.GlobalSunJaasKerberosConfig">
        <beans:property name="debug" value="false" />
        <beans:property name="krbConfLocation" value="file:${externalPropertiesPath}/krb5.conf"/>
    </beans:bean>
Zulemazullo answered 5/8, 2015 at 15:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.