Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SHIRO-841 - NullPointerException from SessionsSecurityManager.start() #329

Merged
merged 2 commits into from
Jan 15, 2022

Conversation

zeroflag
Copy link
Contributor

@zeroflag zeroflag commented Nov 4, 2021

We see this NPE intermittently from KNOX when a topology is being redeployed and a request is still being processed in Shiro's AuthenticatingFilter.

log.trace("Starting session for host {}", getHost());
SessionContext sessionContext = createSessionContext();
// At this point the topology deploy already triggered a securityManager.destroy() so sessionManager is null
Session session = this.securityManager.start(sessionContext);  // <- NPE comes from here
this.session = decorate(session); 
2020-03-17 15:13:08,878 ERROR knox.gateway (AbstractGatewayFilter.java:doFilter(60)) - Failed to execute filter: javax.servlet.ServletException: java.lang.NullPointerException
2020-03-17 15:13:08,878 ERROR knox.gateway (AbstractGatewayFilter.java:doFilter(60)) - Failed to execute filter: javax.servlet.ServletException: java.lang.NullPointerException
2020-03-17 15:13:08,878 ERROR knox.gateway (GatewayFilter.java:doFilter(169)) - Gateway processing failed: javax.servlet.ServletException: java.lang.NullPointerException
javax.servlet.ServletException: java.lang.NullPointerException
	at org.apache.shiro.web.servlet.AdviceFilter.cleanup(AdviceFilter.java:196)
	at org.apache.shiro.web.filter.authc.AuthenticatingFilter.cleanup(AuthenticatingFilter.java:155)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:148)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
	at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
	at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
	at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
	at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:349)
	at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:263)
	at org.apache.knox.gateway.filter.ResponseCookieFilter.doFilter(ResponseCookieFilter.java:49)
	at org.apache.knox.gateway.filter.AbstractGatewayFilter.doFilter(AbstractGatewayFilter.java:58)
	at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:349)
	at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:263)
	at org.apache.knox.gateway.filter.XForwardedHeaderFilter.doFilter(XForwardedHeaderFilter.java:50)
	at org.apache.knox.gateway.filter.AbstractGatewayFilter.doFilter(AbstractGatewayFilter.java:58)
	at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:349)
	at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:263)
	at org.apache.knox.gateway.GatewayFilter.doFilter(GatewayFilter.java:167)
	at org.apache.knox.gateway.GatewayFilter.doFilter(GatewayFilter.java:92)
	at org.apache.knox.gateway.GatewayServlet.service(GatewayServlet.java:135)
	at org.eclipse.jetty.servlet.ServletHolder$NotAsyncServlet.service(ServletHolder.java:1386)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:755)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1617)
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:226)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:545)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:590)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1607)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1297)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1577)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1212)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:221)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.apache.knox.gateway.trace.TraceHandler.handle(TraceHandler.java:51)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.apache.knox.gateway.filter.CorrelationHandler.handle(CorrelationHandler.java:41)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.apache.knox.gateway.filter.PortMappingHelperHandler.handle(PortMappingHelperHandler.java:106)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.eclipse.jetty.websocket.server.WebSocketHandler.handle(WebSocketHandler.java:115)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.eclipse.jetty.server.Server.handle(Server.java:500)
	at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
	at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:547)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:270)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:543)
	at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:398)
	at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:161)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:388)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
	at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
	at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:340)
	at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:316)
	at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:207)
	at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:165)
	at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:146)
	at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:388)
	at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:355)
	at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:188)
	at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:288)
	at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:260)
	at org.apache.shiro.web.filter.authc.AuthenticatingFilter.executeLogin(AuthenticatingFilter.java:53)
	at org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter.onAccessDenied(BasicHttpAuthenticationFilter.java:245)
	at org.apache.shiro.web.filter.AccessControlFilter.onAccessDenied(AccessControlFilter.java:133)
	at org.apache.shiro.web.filter.AccessControlFilter.onPreHandle(AccessControlFilter.java:162)
	at org.apache.shiro.web.filter.PathMatchingFilter.isFilterChainContinued(PathMatchingFilter.java:203)
	at org.apache.shiro.web.filter.PathMatchingFilter.preHandle(PathMatchingFilter.java:178)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:131)
	... 72 more

I see no way to handle this case on the KNOX side.

I think in this case the request is already far gone and it's hopeless to save, so some kind of Error is perfectly fine. But the NPE suggest a programming error in the software while this is rather a normal operation.

This patch just makes this more clear by throwing an IllegalStateException instead of the NullPointerException.

I couldn't find existing unit tests for this class, but let me know if you wan't me to add a unit test.

…r.java

Co-authored-by: Brian Demers <brian.demers@gmail.com>
Copy link
Contributor

@bmarwell bmarwell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Do we want to port this to a 1.8.1 or 1.9.0? I'd say as a bugfix, a 1.8.1 makes sense.

@fpapon
Copy link
Member

fpapon commented Nov 5, 2021

LGTM. Do we want to port this to a 1.8.1 or 1.9.0? I'd say as a bugfix, a 1.8.1 makes sense.

+1 for 1.8.1

@smolnar82
Copy link

@bmarwell - Any hints on when this change is going to be merged and in which version(s) will be available?
Thanks!

@sunshineandy
Copy link

sunshineandy commented Jan 3, 2022 via email

Copy link

@smolnar82 smolnar82 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bmarwell
Copy link
Contributor

It looks we're doing a 1.9.0 release.
@fpapon would you merge this and cherry pick into 1.9.x please?

@fpapon fpapon merged commit da7448f into apache:main Jan 15, 2022
@fpapon
Copy link
Member

fpapon commented Jan 15, 2022

@bmarwell done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
6 participants