From ac2617b92ac0141d5681076eb41eba7521866315 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 3 Nov 2014 12:07:35 -0800 Subject: [PATCH] GUAC-919: Separate auth stuff into own module. Automatically shutdown TokenSessionMap when application is destroyed. --- .../basic/BasicServletContextListener.java | 20 +++- .../net/basic/rest/RESTAuthModule.java | 97 +++++++++++++++++++ .../guacamole/net/basic/rest/RESTModule.java | 39 +------- .../basic/rest/auth/BasicTokenSessionMap.java | 2 + 4 files changed, 119 insertions(+), 39 deletions(-) create mode 100644 guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTAuthModule.java diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicServletContextListener.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicServletContextListener.java index d7ba6b499..ab028157e 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicServletContextListener.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicServletContextListener.java @@ -25,9 +25,13 @@ package org.glyptodon.guacamole.net.basic; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.servlet.GuiceServletContextListener; +import javax.servlet.ServletContextEvent; import org.glyptodon.guacamole.net.basic.log.LogModule; +import org.glyptodon.guacamole.net.basic.rest.RESTAuthModule; import org.glyptodon.guacamole.net.basic.rest.RESTModule; import org.glyptodon.guacamole.net.basic.rest.RESTServletModule; +import org.glyptodon.guacamole.net.basic.rest.auth.BasicTokenSessionMap; +import org.glyptodon.guacamole.net.basic.rest.auth.TokenSessionMap; /** * A ServletContextListener to listen for initialization of the servlet context @@ -37,15 +41,29 @@ import org.glyptodon.guacamole.net.basic.rest.RESTServletModule; */ public class BasicServletContextListener extends GuiceServletContextListener { + /** + * Singleton instance of a TokenSessionMap. + */ + private final TokenSessionMap sessionMap = new BasicTokenSessionMap(); + @Override protected Injector getInjector() { - return Guice.createInjector( new LogModule(), new RESTServletModule(), + new RESTAuthModule(sessionMap), new RESTModule(), new TunnelModule() ); + } + + @Override + public void contextDestroyed(ServletContextEvent servletContextEvent) { + + // Shutdown TokenSessionMap + sessionMap.shutdown(); + + super.contextDestroyed(servletContextEvent); } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTAuthModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTAuthModule.java new file mode 100644 index 000000000..456c883d2 --- /dev/null +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTAuthModule.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2014 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.glyptodon.guacamole.net.basic.rest; + +import com.google.inject.AbstractModule; +import com.google.inject.matcher.Matchers; +import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.net.auth.AuthenticationProvider; +import org.glyptodon.guacamole.net.basic.properties.BasicGuacamoleProperties; +import org.glyptodon.guacamole.net.basic.rest.auth.AuthTokenGenerator; +import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService; +import org.glyptodon.guacamole.net.basic.rest.auth.SecureRandomAuthTokenGenerator; +import org.glyptodon.guacamole.net.basic.rest.auth.TokenSessionMap; +import org.glyptodon.guacamole.properties.GuacamoleProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A Guice Module for setting up authentication-specific dependency injection. + * + * @author James Muehlner + * @author Michael Jumper + */ +public class RESTAuthModule extends AbstractModule { + + /** + * Logger for this class. + */ + private static final Logger logger = LoggerFactory.getLogger(RESTAuthModule.class); + + /** + * The AuthenticationProvider to use to authenticate all requests. + */ + private AuthenticationProvider authProvider; + + /** + * Singleton instance of a TokenSessionMap. + */ + private final TokenSessionMap sessionMap; + + /** + * Creates a module which handles binding of authentication-related + * objects, including the singleton TokenSessionMap. + * + * @param sessionMap An instance of TokenSessionMap to inject as a singleton + * wherever needed. + */ + public RESTAuthModule(TokenSessionMap sessionMap) { + this.sessionMap = sessionMap; + } + + @Override + protected void configure() { + + // Get and bind auth provider instance + try { + authProvider = GuacamoleProperties.getRequiredProperty(BasicGuacamoleProperties.AUTH_PROVIDER); + bind(AuthenticationProvider.class).toInstance(authProvider); + } + catch (GuacamoleException e) { + logger.error("Unable to read authentication provider from guacamole.properties: {}", e.getMessage()); + logger.debug("Error reading authentication provider from guacamole.properties.", e); + throw new RuntimeException(e); + } + + // Bind singleton TokenSessionMap + bind(TokenSessionMap.class).toInstance(sessionMap); + + bind(AuthenticationService.class); + bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class); + + // Bind @AuthProviderRESTExposure annotation + bindInterceptor(Matchers.any(), Matchers.annotatedWith(AuthProviderRESTExposure.class), new AuthProviderRESTExceptionWrapper()); + + } + +} diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTModule.java index 049f37a7e..55e473755 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTModule.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTModule.java @@ -23,23 +23,11 @@ package org.glyptodon.guacamole.net.basic.rest; import com.google.inject.AbstractModule; -import com.google.inject.matcher.Matchers; -import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.net.auth.AuthenticationProvider; -import org.glyptodon.guacamole.net.basic.properties.BasicGuacamoleProperties; -import org.glyptodon.guacamole.net.basic.rest.auth.AuthTokenGenerator; -import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService; -import org.glyptodon.guacamole.net.basic.rest.auth.BasicTokenSessionMap; -import org.glyptodon.guacamole.net.basic.rest.auth.SecureRandomAuthTokenGenerator; -import org.glyptodon.guacamole.net.basic.rest.auth.TokenSessionMap; import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionService; import org.glyptodon.guacamole.net.basic.rest.connectiongroup.ConnectionGroupService; import org.glyptodon.guacamole.net.basic.rest.permission.PermissionService; import org.glyptodon.guacamole.net.basic.rest.protocol.ProtocolRetrievalService; import org.glyptodon.guacamole.net.basic.rest.user.UserService; -import org.glyptodon.guacamole.properties.GuacamoleProperties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * A Guice Module for setting up dependency injection for the @@ -49,41 +37,16 @@ import org.slf4j.LoggerFactory; */ public class RESTModule extends AbstractModule { - /** - * Logger for this class. - */ - private static final Logger logger = LoggerFactory.getLogger(RESTModule.class); - - /** - * The AuthenticationProvider to use to authenticate all requests. - */ - private AuthenticationProvider authProvider; - @Override protected void configure() { - // Get auth provider instance - try { - authProvider = GuacamoleProperties.getRequiredProperty(BasicGuacamoleProperties.AUTH_PROVIDER); - } - catch (GuacamoleException e) { - logger.error("Unable to read authentication provider from guacamole.properties: {}", e.getMessage()); - logger.debug("Error reading authentication provider from guacamole.properties.", e); - throw new RuntimeException(e); - } - - bind(AuthenticationProvider.class).toInstance(authProvider); - bind(TokenSessionMap.class).toInstance(new BasicTokenSessionMap()); + // Bind generic low-level services bind(ConnectionService.class); bind(ConnectionGroupService.class); bind(PermissionService.class); bind(UserService.class); - bind(AuthenticationService.class); bind(ProtocolRetrievalService.class); - bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class); - - bindInterceptor(Matchers.any(), Matchers.annotatedWith(AuthProviderRESTExposure.class), new AuthProviderRESTExceptionWrapper()); } } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/BasicTokenSessionMap.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/BasicTokenSessionMap.java index 50344f484..9e5101449 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/BasicTokenSessionMap.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/BasicTokenSessionMap.java @@ -22,6 +22,7 @@ package org.glyptodon.guacamole.net.basic.rest.auth; +import com.google.inject.Singleton; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; @@ -42,6 +43,7 @@ import org.slf4j.LoggerFactory; * * @author James Muehlner */ +@Singleton public class BasicTokenSessionMap implements TokenSessionMap { /**