SPNEGO/SSO - can't load spnego.krb5.conf

Hi there,

I’ve some issues with the SSO / SPNEGO auth module and I hope someone can help to nail this issue.

Fess complains that he can’t find the spnego.krb5.conf

Caused by: java.lang.IllegalArgumentException: Servlet Filter init param(s) in web.xml missing: spnego.krb5.conf

which is set and is accessible by Fess in system.properties.

sso.type=spnego
spnego.logger.level=3
spnego.krb5.conf=/etc/fess/krb5.conf
spnego.login.conf=/etc/fess/auth_login.conf
spnego.preauth.username=*****
spnego.preauth.password=******
spnego.login.client.module=spnego-client
spnego.login.server.module=spnego-server
spnego.allow.basic=true
spnego.allow.unsecure.basic=true
spnego.prompt.ntlm=true
spnego.allow.localhost=true
spnego.allow.delegation=false
spnego.initialized=true

I’m running FESS 13.1.1 as a Docker Container, and the config files are mounted as a docker volume to /etc/fess. Actually digging into the code I think the issue is related to loading the krb5.conf file starting in the class SpnegoAuthenticator in the method getAuthenticator()

With the following call hierarchy, SpnegoFilterConfig tries to load the config value for Constants.KRB5_CONF calling the method getResourcePath(...) in the class ‘SpnegoAuthenticator .SpengoConfig’ which also uses the util method ResourceUtil.getResourceAsFileNoException(path); which returns null I guess.

The path value is set and is accessible at /etc/fess/krb5.conf.
Any Ideas why the SSO is not working anymore? I think that this issue popped up when we upgraded from 12.x to 13.x.

Here is the “Bug/Report” list from the admin dasboard:

file.separator=/
file.encoding=UTF-8
java.runtime.version=11.0.3+7-Debian-1bpo92
java.vm.info=mixed mode, sharing
java.vm.name=OpenJDK 64-Bit Server VM
java.vm.vendor=Oracle Corporation
java.vm.version=11.0.3+7-Debian-1bpo92
os.arch=amd64
os.name=Linux
os.version=3.10.0-862.9.1.el7.x86_64
user.country=US
user.language=en
user.timezone=Etc/UTC
suggest.document=true
ldap.admin.security.principal=*****
purge.searchlog.day=14
append.query.parameter=false
sso.type=spnego
spnego.logger.level=3
spnego.preauth.password=*****
web.api.popularword=true
purge.suggest.searchlog.day=30
user.favorite=false
login.link.enabled=true
ldap.provider.url=ldap://172.30.9.2
login.required=true
result.collapsed=false
spnego.prompt.ntlm=true
notification.to=*****
spnego.login.client.module=spnego-client
csv.file.encoding=UTF-8
crawling.incremental=true
spnego.allow.basic=true
failure.countthreshold=-1
spnego.login.conf=/etc/fess/auth_login.conf
thumbnail.enabled=false
spnego.krb5.conf=/etc/fess/krb5.conf
search.log=true
purge.userinfo.day=14
ldap.base.dn=dc=dd,dc=local
ldap.admin.security.credentials=******
purge.joblog.day=14
purge.by.bots=Crawler
spnego.allow.unsecure.basic=true
spnego.preauth.username=*****
ldap.account.filter=(sAMAccountName=%s)
user.info=false
ldap.security.principal=%s@dd.local
spnego.allow.delegation=false
spnego.login.server.module=spnego-server
crawling.thread.count=10
ldap.memberof.attribute=memberOf
spnego.allow.localhost=true
web.api.json=true
day.for.cleanup=14
suggest.searchlog=true

And the Exception from the logs:

org.codelibs.fess.exception.SsoLoginException: HTTP Authorization Header=null
    	at org.codelibs.fess.sso.spnego.SpnegoAuthenticator.lambda$getLoginCredential$1(SpnegoAuthenticator.java:114)
    	at org.dbflute.optional.BaseOptional.callbackMapping(BaseOptional.java:228)
    	at org.dbflute.optional.OptionalObject.map(OptionalObject.java:123)
    	at org.codelibs.fess.sso.spnego.SpnegoAuthenticator.getLoginCredential(SpnegoAuthenticator.java:101)
    	at org.codelibs.fess.sso.SsoManager.getLoginCredential(SsoManager.java:42)
    	at org.codelibs.fess.app.web.sso.SsoAction.index(SsoAction.java:48)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    	at org.lastaflute.web.ruts.GodHandableAction.invokeExecuteMethod(GodHandableAction.java:335)
    	at org.lastaflute.web.ruts.GodHandableAction.actuallyExecute(GodHandableAction.java:306)
    	at org.lastaflute.web.ruts.GodHandableAction.doExecute(GodHandableAction.java:146)
    	at org.lastaflute.web.ruts.GodHandableAction.lambda$transactionalExecute$0(GodHandableAction.java:137)
    	at org.lastaflute.db.jta.stage.JTATransactionStage.performTx(JTATransactionStage.java:102)
    	at org.lastaflute.db.jta.stage.JTATransactionStage.lambda$requiresNew$1(JTATransactionStage.java:59)
    	at org.lastaflute.di.tx.adapter.JTATransactionManagerAdapter.requiresNew(JTATransactionManagerAdapter.java:73)
    	at org.lastaflute.db.jta.stage.JTATransactionStage.requiresNew(JTATransactionStage.java:58)
    	at org.lastaflute.db.jta.stage.JTATransactionStage.selectable(JTATransactionStage.java:84)
    	at org.lastaflute.web.ruts.GodHandableAction.transactionalExecute(GodHandableAction.java:136)
    	at org.lastaflute.web.ruts.GodHandableAction.execute(GodHandableAction.java:117)
    	at org.lastaflute.web.ruts.ActionRequestProcessor.performAction(ActionRequestProcessor.java:253)
    	at org.lastaflute.web.ruts.ActionRequestProcessor.fire(ActionRequestProcessor.java:182)
    	at org.lastaflute.web.ruts.ActionRequestProcessor.process(ActionRequestProcessor.java:114)
    	at org.lastaflute.web.servlet.filter.RequestRoutingFilter.processAction(RequestRoutingFilter.java:266)
    	at org.lastaflute.web.servlet.filter.RequestRoutingFilter.routingToAction(RequestRoutingFilter.java:218)
    	at org.lastaflute.web.servlet.filter.RequestRoutingFilter.lambda$createActionFoundPathHandler$0(RequestRoutingFilter.java:184)
    	at org.lastaflute.web.path.ActionPathResolver.executeHandlerIfFound(ActionPathResolver.java:342)
    	at org.lastaflute.web.path.ActionPathResolver.mappingActionPath(ActionPathResolver.java:208)
    	at org.lastaflute.web.path.ActionPathResolver.handleActionPath(ActionPathResolver.java:113)
    	at org.lastaflute.web.servlet.filter.RequestRoutingFilter.doFilter(RequestRoutingFilter.java:118)
    	at org.lastaflute.web.servlet.filter.LastaToActionFilter.viaEmbeddedFilter(LastaToActionFilter.java:153)
    	at org.lastaflute.web.servlet.filter.LastaToActionFilter.viaInsideHookDeque(LastaToActionFilter.java:144)
    	at org.lastaflute.web.servlet.filter.LastaToActionFilter.viaInsideHook(LastaToActionFilter.java:128)
    	at org.lastaflute.web.servlet.filter.LastaToActionFilter.doFilter(LastaToActionFilter.java:120)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.lastaflute.web.servlet.filter.LastaShowbaseFilter.toNextChain(LastaShowbaseFilter.java:171)
    	at org.lastaflute.web.servlet.filter.LastaShowbaseFilter.lambda$viaEmbeddedFilter$3(LastaShowbaseFilter.java:150)
    	at org.lastaflute.web.servlet.filter.RequestLoggingFilter.actuallyFilter(RequestLoggingFilter.java:237)
    	at org.lastaflute.web.servlet.filter.RequestLoggingFilter.doFilter(RequestLoggingFilter.java:209)
    	at org.lastaflute.web.servlet.filter.LastaShowbaseFilter.viaEmbeddedFilter(LastaShowbaseFilter.java:148)
    	at org.lastaflute.web.servlet.filter.LastaShowbaseFilter.viaOutsideHookDeque(LastaShowbaseFilter.java:139)
    	at org.lastaflute.web.servlet.filter.LastaShowbaseFilter.viaOutsideHook(LastaShowbaseFilter.java:123)
    	at org.lastaflute.web.servlet.filter.LastaShowbaseFilter.doFilter(LastaShowbaseFilter.java:115)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.codelibs.fess.filter.WebApiFilter.doFilter(WebApiFilter.java:51)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.codelibs.fess.filter.CorsFilter.doFilter(CorsFilter.java:58)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.lastaflute.web.servlet.filter.LastaPrepareFilter.toNextFilter(LastaPrepareFilter.java:280)
    	at org.lastaflute.web.servlet.filter.LastaPrepareFilter.viaHotdeploy(LastaPrepareFilter.java:243)
    	at org.lastaflute.web.servlet.filter.LastaPrepareFilter.viaLastaDiContext(LastaPrepareFilter.java:230)
    	at org.lastaflute.web.servlet.filter.LastaPrepareFilter.doFilter(LastaPrepareFilter.java:203)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.codelibs.fess.filter.EncodingFilter.doFilter(EncodingFilter.java:119)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836)
    	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1839)
    	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    	at java.base/java.lang.Thread.run(Thread.java:834)
    Caused by: org.codelibs.fess.exception.SsoLoginException: Failed to initialize SPNEGO.
    	at org.codelibs.fess.sso.spnego.SpnegoAuthenticator.getAuthenticator(SpnegoAuthenticator.java:90)
    	at org.codelibs.fess.sso.spnego.SpnegoAuthenticator.lambda$getLoginCredential$1(SpnegoAuthenticator.java:108)
    	... 77 more
    Caused by: java.lang.IllegalArgumentException: Servlet Filter init param(s) in web.xml missing: spnego.krb5.conf
    	at org.codelibs.spnego.SpnegoFilterConfig.<init>(SpnegoFilterConfig.java:127)
    	at org.codelibs.spnego.SpnegoFilterConfig.getInstance(SpnegoFilterConfig.java:341)
    	at org.codelibs.fess.sso.spnego.SpnegoAuthenticator.getAuthenticator(SpnegoAuthenticator.java:81)

It seems not to read the value from system.properties…
Is this problem reproduced in the latest version?