Mercurial > hg > thermostat-ng > web-gateway
changeset 232:8fe9127fb648
Enable basic authentication by default
Reviewed-by: jerboaa
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-August/024617.html
line wrap: on
line diff
--- a/common/core/src/main/java/com/redhat/thermostat/gateway/common/core/auth/DefaultRealmAuthorizer.java Mon Aug 21 16:44:08 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.gateway.common.core.auth; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -public class DefaultRealmAuthorizer extends RealmAuthorizer { - public static final String DEFAULT_REALM = "thermostat"; - - public DefaultRealmAuthorizer() throws InvalidRoleException { - RoleFactory roleFactory = new RoleFactory(); - Role r = roleFactory.buildRole("r,w,u,d-" + DEFAULT_REALM); - Set<Role> roles = new HashSet<>(); - roles.add(r); - - clientRoles = Collections.unmodifiableSet(roles); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/gateway/common/core/auth/basic/BasicRealmAuthorizer.java Wed Aug 23 08:34:51 2017 -0400 @@ -0,0 +1,70 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.gateway.common.core.auth.basic; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import com.redhat.thermostat.gateway.common.core.auth.InvalidRoleException; +import com.redhat.thermostat.gateway.common.core.auth.RealmAuthorizer; +import com.redhat.thermostat.gateway.common.core.auth.Role; +import com.redhat.thermostat.gateway.common.core.auth.RoleFactory; +import com.redhat.thermostat.gateway.common.core.auth.basic.BasicWebUser; + +public class BasicRealmAuthorizer extends RealmAuthorizer { + public static final String DEFAULT_REALM = "thermostat"; + + public BasicRealmAuthorizer(BasicWebUser user) throws InvalidRoleException { + RoleFactory roleFactory = new RoleFactory(); + + Set<Role> roles = new HashSet<>(); + for (String role : user.getRoles()) { + Role r = roleFactory.buildRole(role); + roles.add(r); + } + + clientRoles = Collections.unmodifiableSet(roles); + } + + /** + * Package private for testing + */ + Set<Role> getAllRoles() { + return clientRoles; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/gateway/common/core/auth/basic/BasicWebUser.java Wed Aug 23 08:34:51 2017 -0400 @@ -0,0 +1,69 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.gateway.common.core.auth.basic; + +import java.util.Set; + +public class BasicWebUser implements RoleAwareUser { + private final String username; + private final Set<String> roles; + private final char[] password; + + public BasicWebUser(String username, char[] password, Set<String> roles) { + this.username = username; + this.roles = roles; + this.password = password; + } + + @Override + public String getName() { + return this.username; + } + + @Override + public boolean isUserInRole(String role) { + return this.roles.contains(role); + } + + public String getPassword() { + return new String(password); + } + + public Set<String> getRoles() { + return roles; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/gateway/common/core/config/IllegalConfigurationException.java Wed Aug 23 08:34:51 2017 -0400 @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.gateway.common.core.config; + +public class IllegalConfigurationException extends RuntimeException { + public IllegalConfigurationException(String s) { + super(s); + } +}
--- a/common/core/src/main/java/com/redhat/thermostat/gateway/common/core/config/ServiceConfiguration.java Mon Aug 21 16:44:08 2017 -0400 +++ b/common/core/src/main/java/com/redhat/thermostat/gateway/common/core/config/ServiceConfiguration.java Wed Aug 23 08:34:51 2017 -0400 @@ -58,13 +58,17 @@ } public enum ConfigurationKey { + /** - * Set to {@code true} for basic authentication + * Set to {@code true} for BASIC authentication + * and authorization. Disabled if SECURITY_KEYCLOAK + * is also {@code true} */ SECURITY_BASIC, /** - * Only useful together with SECURITY_BASIC. - * Specifies the users a service knows about. + * Specifies the users a service knows about for + * BASIC authentication and authorization. Only + * useful together with SECURITY_BASIC */ SECURITY_BASIC_USERS, /** @@ -74,9 +78,8 @@ WEBSOCKETS, /** - * Set to {@code true} for keycloak authentication - * and authorization. Cannot be used along with - * {@link ConfigurationKey#SECURITY_BASIC} + * Set to {@code true} for Keycloak authentication + * and authorization. Disables Basic authentication */ SECURITY_KEYCLOAK,
--- a/common/core/src/test/java/com/redhat/thermostat/gateway/common/core/auth/DefaultRealmAuthorizerTest.java Mon Aug 21 16:44:08 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.gateway.common.core.auth; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class DefaultRealmAuthorizerTest { - - @Test - public void testDefaultRoleExists() throws InvalidRoleException { - DefaultRealmAuthorizer realmAuthorizer = new DefaultRealmAuthorizer(); - - assertEquals(1, realmAuthorizer.clientRoles.size()); - - for (Role r : realmAuthorizer.clientRoles) { - assertEquals("thermostat", r.getRealm()); - assertTrue(r.containsAction("r")); - assertTrue(r.containsAction("w")); - assertTrue(r.containsAction("u")); - assertTrue(r.containsAction("d")); - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/test/java/com/redhat/thermostat/gateway/common/core/auth/basic/BasicRealmAuthorizerTest.java Wed Aug 23 08:34:51 2017 -0400 @@ -0,0 +1,73 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.gateway.common.core.auth.basic; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashSet; +import java.util.Set; + +import org.junit.Test; + +import com.redhat.thermostat.gateway.common.core.auth.InvalidRoleException; +import com.redhat.thermostat.gateway.common.core.auth.Role; + +public class BasicRealmAuthorizerTest { + + @Test + public void testDefaultRoleExists() throws InvalidRoleException { + BasicWebUser basicWebUser = mock(BasicWebUser.class); + Set<String> mockRoles = new HashSet<>(); + mockRoles.add("r,w,u,d-thermostat"); + when(basicWebUser.getRoles()).thenReturn(mockRoles); + + BasicRealmAuthorizer realmAuthorizer = new BasicRealmAuthorizer(basicWebUser); + + assertEquals(1, realmAuthorizer.getAllRoles().size()); + + for (Role r : realmAuthorizer.getAllRoles()) { + assertEquals("thermostat", r.getRealm()); + assertTrue(r.containsAction("r")); + assertTrue(r.containsAction("w")); + assertTrue(r.containsAction("u")); + assertTrue(r.containsAction("d")); + } + } +}
--- a/distribution/src/etc/basic-config.properties Mon Aug 21 16:44:08 2017 -0400 +++ b/distribution/src/etc/basic-config.properties Wed Aug 23 08:34:51 2017 -0400 @@ -1,1 +1,2 @@ -admin=password,thermostat-admin \ No newline at end of file +agent=agent-pwd,r-thermostat,w-thermostat,u-thermostat,d-thermostat +client=client-pwd,r-thermostat \ No newline at end of file
--- a/distribution/src/etc/global-config.properties Mon Aug 21 16:44:08 2017 -0400 +++ b/distribution/src/etc/global-config.properties Wed Aug 23 08:34:51 2017 -0400 @@ -5,6 +5,10 @@ # The file specifying which services to deploy in the # servlet container. properties|SERVICES=services.properties +# Sets auth scheme to BASIC +SECURITY_BASIC=true +# Specifies location of BASIC AUTH credentials +properties|SECURITY_BASIC_USERS=basic-config.properties # # Specifies whether or not the swagger UI handler should get # created under context path /doc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/main/java/com/redhat/thermostat/gateway/server/auth/BasicAuthFilter.java Wed Aug 23 08:34:51 2017 -0400 @@ -0,0 +1,129 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.gateway.server.auth; + +import java.io.IOException; +import java.nio.charset.Charset; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.NotAuthorizedException; +import javax.ws.rs.core.HttpHeaders; +import javax.xml.bind.DatatypeConverter; + +import com.redhat.thermostat.gateway.common.core.auth.basic.BasicRealmAuthorizer; +import com.redhat.thermostat.gateway.common.core.auth.InvalidRoleException; +import com.redhat.thermostat.gateway.common.core.auth.RealmAuthorizer; +import com.redhat.thermostat.gateway.server.auth.basic.BasicUserStore; +import com.redhat.thermostat.gateway.common.core.auth.basic.BasicWebUser; + +public class BasicAuthFilter implements Filter { + private BasicUserStore userStore; + + public BasicAuthFilter(BasicUserStore userStore) { + this.userStore = userStore; + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + // Do nothing + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest httpServletRequest = (HttpServletRequest) request; + + String authentication = httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION); + if (authentication == null) { + sendHttpUnauth(response); + return; + } + + if (!authentication.startsWith("Basic ")) { + sendHttpUnauth(response); + return; + } + + authentication = authentication.substring("Basic ".length()); + String[] values = new String(DatatypeConverter.parseBase64Binary(authentication), + Charset.forName("ASCII")).split(":"); + if (values.length < 2) { + sendHttpUnauth(response); + return; + } + + String username = values[0]; + String password = values[1]; + + BasicWebUser user = userStore.getUser(username); + if (user == null) { + sendHttpUnauth(response); + return; + } + + if (!user.getPassword().equals(password)) { + sendHttpUnauth(response); + return; + } + + try { + RealmAuthorizer realmAuthorizer = new BasicRealmAuthorizer(user); + httpServletRequest.setAttribute(RealmAuthorizer.class.getName(), realmAuthorizer); + + chain.doFilter(request, response); + } catch (InvalidRoleException e) { + throw new IllegalStateException("Unable to create DefaultRealmAuthorizer", e); + } + } + + private void sendHttpUnauth(ServletResponse response) throws IOException { + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + httpServletResponse.setHeader("WWW-Authenticate", "Basic realm=\"thermostat\""); + httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); + } + + @Override + public void destroy() { + // Do nothing + } +}
--- a/server/src/main/java/com/redhat/thermostat/gateway/server/auth/DefaultAuthFilter.java Mon Aug 21 16:44:08 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.gateway.server.auth; - -import java.io.IOException; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; - -import com.redhat.thermostat.gateway.common.core.auth.DefaultRealmAuthorizer; -import com.redhat.thermostat.gateway.common.core.auth.InvalidRoleException; -import com.redhat.thermostat.gateway.common.core.auth.RealmAuthorizer; - -public class DefaultAuthFilter implements Filter { - private RealmAuthorizer realmAuthorizer; - - public DefaultAuthFilter() { - try { - realmAuthorizer = new DefaultRealmAuthorizer(); - } catch (InvalidRoleException e) { - throw new IllegalStateException("Unable to create DefaultRealmAuthorizer", e); - } - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - // Do nothing - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - HttpServletRequest httpServletRequest = (HttpServletRequest) request; - httpServletRequest.setAttribute(RealmAuthorizer.class.getName(), realmAuthorizer); - - chain.doFilter(request, response); - } - - @Override - public void destroy() { - // Do nothing - } -}
--- a/server/src/main/java/com/redhat/thermostat/gateway/server/auth/basic/BasicLoginService.java Mon Aug 21 16:44:08 2017 -0400 +++ b/server/src/main/java/com/redhat/thermostat/gateway/server/auth/basic/BasicLoginService.java Wed Aug 23 08:34:51 2017 -0400 @@ -46,6 +46,8 @@ import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.server.UserIdentity; +import com.redhat.thermostat.gateway.common.core.auth.basic.BasicWebUser; + public class BasicLoginService implements LoginService { private final BasicUserStore store; @@ -64,7 +66,7 @@ @Override public UserIdentity login(final String username, Object credentials) { - BasicWebUser user = (BasicWebUser)store.getUser(username); + BasicWebUser user = store.getUser(username); if (user == null) { return null; }
--- a/server/src/main/java/com/redhat/thermostat/gateway/server/auth/basic/BasicUserStore.java Mon Aug 21 16:44:08 2017 -0400 +++ b/server/src/main/java/com/redhat/thermostat/gateway/server/auth/basic/BasicUserStore.java Wed Aug 23 08:34:51 2017 -0400 @@ -42,11 +42,11 @@ import java.util.HashSet; import java.util.Map; -import com.redhat.thermostat.gateway.common.core.auth.basic.RoleAwareUser; +import com.redhat.thermostat.gateway.common.core.auth.basic.BasicWebUser; public class BasicUserStore { - private final Map<String, RoleAwareUser> users = new HashMap<>(); + private final Map<String, BasicWebUser> users = new HashMap<>(); public BasicUserStore(Map<String, String> userConfig) { for (Map.Entry<String, String> entry : userConfig.entrySet()) { @@ -57,7 +57,7 @@ } } - public RoleAwareUser getUser(String userName) { + public BasicWebUser getUser(String userName) { return users.get(userName); } }
--- a/server/src/main/java/com/redhat/thermostat/gateway/server/auth/basic/BasicWebUser.java Mon Aug 21 16:44:08 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.gateway.server.auth.basic; - -import java.util.Set; - -import com.redhat.thermostat.gateway.common.core.auth.basic.RoleAwareUser; - -public class BasicWebUser implements RoleAwareUser { - private final String username; - private final Set<String> roles; - private final char[] password; - - public BasicWebUser(String username, char[] password, Set<String> roles) { - this.username = username; - this.roles = roles; - this.password = password; - } - - @Override - public String getName() { - return this.username; - } - - @Override - public boolean isUserInRole(String role) { - return this.roles.contains(role); - } - - public String getPassword() { - return new String(password); - } - - public Set<String> getRoles() { - return roles; - } -}
--- a/server/src/main/java/com/redhat/thermostat/gateway/server/services/WebArchiveCoreService.java Mon Aug 21 16:44:08 2017 -0400 +++ b/server/src/main/java/com/redhat/thermostat/gateway/server/services/WebArchiveCoreService.java Wed Aug 23 08:34:51 2017 -0400 @@ -50,6 +50,7 @@ import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.SecurityHandler; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.webapp.WebAppContext; @@ -57,9 +58,10 @@ import org.keycloak.adapters.jetty.KeycloakJettyAuthenticator; import com.redhat.thermostat.gateway.common.core.config.Configuration; +import com.redhat.thermostat.gateway.common.core.config.IllegalConfigurationException; import com.redhat.thermostat.gateway.common.core.config.ServiceConfiguration; import com.redhat.thermostat.gateway.common.core.servlet.GlobalConstants; -import com.redhat.thermostat.gateway.server.auth.DefaultAuthFilter; +import com.redhat.thermostat.gateway.server.auth.BasicAuthFilter; import com.redhat.thermostat.gateway.server.auth.basic.BasicLoginService; import com.redhat.thermostat.gateway.server.auth.basic.BasicUserStore; import com.redhat.thermostat.gateway.server.auth.keycloak.KeycloakConfiguration; @@ -98,18 +100,28 @@ } - private void setupAuthForContext(WebAppContext webAppContext) { - if (isSet(ServiceConfiguration.ConfigurationKey.SECURITY_BASIC)) { + private void setupAuthForContext(WebAppContext webAppContext) throws IllegalConfigurationException { + // Check Keycloak first as it has higher priority. Only one auth scheme allowed + if (isSet(ServiceConfiguration.ConfigurationKey.SECURITY_KEYCLOAK)) { + setupKeycloakAuthForContext(webAppContext); + } else if (isSet(ServiceConfiguration.ConfigurationKey.SECURITY_BASIC)) { setupBasicAuthForContext(webAppContext); - } else if (isSet(ServiceConfiguration.ConfigurationKey.SECURITY_KEYCLOAK)) { - setupKeycloakAuthForContext(webAppContext); } else { - setupDefaultAuthForContext(webAppContext); + throw new IllegalConfigurationException("No auth scheme specified."); } } - private void setupDefaultAuthForContext(WebAppContext webAppContext) { - webAppContext.addFilter(DefaultAuthFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + private void setupBasicAuthForContext(WebAppContext webAppContext) { + Map<String, String> userConfig = getBasicAuthUserConfig(); + BasicUserStore userStore = new BasicUserStore(userConfig); + BasicAuthFilter basicAuthFilter = new BasicAuthFilter(userStore); + FilterHolder filterHolder = new FilterHolder(basicAuthFilter); + + webAppContext.addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST)); + + SecurityHandler security = webAppContext.getSecurityHandler(); + LoginService loginService = new BasicLoginService(userStore, security.getRealmName()); + security.setLoginService(loginService); } private void setupKeycloakAuthForContext(WebAppContext webAppContext) { @@ -141,14 +153,6 @@ webAppContext.addFilter(KeycloakRequestFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); } - private void setupBasicAuthForContext(WebAppContext webAppContext) { - Map<String, String> userConfig = getBasicAuthUserConfig(); - SecurityHandler security = webAppContext.getSecurityHandler(); - BasicUserStore userStore = new BasicUserStore(userConfig); - LoginService loginService = new BasicLoginService(userStore, security.getRealmName()); - security.setLoginService(loginService); - } - @SuppressWarnings("unchecked") private Map<String, String> getBasicAuthUserConfig() { if (serviceConfig.asMap().containsKey(ServiceConfiguration.ConfigurationKey.SECURITY_BASIC_USERS.name())) {
--- a/server/src/test/java/com/redhat/thermostat/gateway/server/services/WebArchiveCoreServiceTest.java Mon Aug 21 16:44:08 2017 -0400 +++ b/server/src/test/java/com/redhat/thermostat/gateway/server/services/WebArchiveCoreServiceTest.java Wed Aug 23 08:34:51 2017 -0400 @@ -58,6 +58,8 @@ import org.keycloak.adapters.jetty.KeycloakJettyAuthenticator; import com.redhat.thermostat.gateway.common.core.config.Configuration; +import com.redhat.thermostat.gateway.common.core.config.GlobalConfiguration; +import com.redhat.thermostat.gateway.common.core.config.IllegalConfigurationException; import com.redhat.thermostat.gateway.common.core.config.ServiceConfiguration; import com.redhat.thermostat.gateway.common.core.servlet.GlobalConstants; import com.redhat.thermostat.gateway.server.auth.basic.BasicLoginService; @@ -75,9 +77,22 @@ " \"resource\": \"thermostat-bearer\"\n" + "}"; + @Test(expected = IllegalConfigurationException.class) + public void testNoAuthException() { + Map<String, Object> configurationMap = new HashMap<>(); + + Configuration configuration = mock(Configuration.class); + when(configuration.asMap()).thenReturn(configurationMap); + + WebArchiveCoreService service = new WebArchiveCoreService(contextPath, warPath, configuration); + + service.createServletContextHandler(mock(Server.class)); + } + @Test public void testBasicService() { Map<String, Object> configurationMap = new HashMap<>(); + configurationMap.put(ServiceConfiguration.ConfigurationKey.SECURITY_BASIC.name(), "true"); Configuration configuration = mock(Configuration.class); when(configuration.asMap()).thenReturn(configurationMap); @@ -96,6 +111,7 @@ @Test public void testServiceConfigIsAdded() { Map<String, Object> configurationMap = new HashMap<>(); + configurationMap.put(ServiceConfiguration.ConfigurationKey.SECURITY_BASIC.name(), "true"); Configuration configuration = mock(Configuration.class); when(configuration.asMap()).thenReturn(configurationMap); @@ -172,6 +188,7 @@ @Test public void testServiceWithWebSockets() { Map<String, Object> configurationMap = new HashMap<>(); + configurationMap.put(ServiceConfiguration.ConfigurationKey.SECURITY_BASIC.name(), "true"); configurationMap.put(ServiceConfiguration.ConfigurationKey.WEBSOCKETS.name(), "true"); Configuration configuration = mock(Configuration.class); when(configuration.asMap()).thenReturn(configurationMap);
--- a/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvm/gc/JvmGcServiceIntegrationTest.java Mon Aug 21 16:44:08 2017 -0400 +++ b/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvm/gc/JvmGcServiceIntegrationTest.java Wed Aug 23 08:34:51 2017 -0400 @@ -46,7 +46,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; -import com.redhat.thermostat.gateway.common.core.auth.DefaultRealmAuthorizer; +import com.redhat.thermostat.gateway.common.core.auth.basic.BasicRealmAuthorizer; import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters; import com.redhat.thermostat.gateway.tests.integration.MongoIntegrationTest; import org.bson.Document; @@ -413,7 +413,7 @@ documents.forEach(new Block<Document>() { @Override public void apply(Document document) { - assertEquals(getRealmArray(DefaultRealmAuthorizer.DEFAULT_REALM), gson.toJson(document.get("realms"), listType)); + assertEquals(getRealmArray(BasicRealmAuthorizer.DEFAULT_REALM), gson.toJson(document.get("realms"), listType)); } }); } @@ -466,7 +466,7 @@ documents.forEach(new Block<Document>() { @Override public void apply(Document document) { - assertEquals(getRealmArray(DefaultRealmAuthorizer.DEFAULT_REALM), gson.toJson(document.get("realms"), listType)); + assertEquals(getRealmArray(BasicRealmAuthorizer.DEFAULT_REALM), gson.toJson(document.get("realms"), listType)); } }); } @@ -502,7 +502,7 @@ ContentResponse response = client.newRequest(gcUrl) - .param(RequestParameters.QUERY, "realms==" + getRealmArray(DefaultRealmAuthorizer.DEFAULT_REALM)) + .param(RequestParameters.QUERY, "realms==" + getRealmArray(BasicRealmAuthorizer.DEFAULT_REALM)) .method(HttpMethod.GET).send(); assertEquals(400, response.getStatus()); @@ -524,7 +524,7 @@ documents.forEach(new Block<Document>() { @Override public void apply(Document document) { - assertEquals(getRealmArray(DefaultRealmAuthorizer.DEFAULT_REALM), gson.toJson(document.get("realms"), listType)); + assertEquals(getRealmArray(BasicRealmAuthorizer.DEFAULT_REALM), gson.toJson(document.get("realms"), listType)); } }); }
--- a/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/tests/integration/IntegrationTest.java Mon Aug 21 16:44:08 2017 -0400 +++ b/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/tests/integration/IntegrationTest.java Wed Aug 23 08:34:51 2017 -0400 @@ -37,11 +37,14 @@ package com.redhat.thermostat.gateway.tests.integration; import java.io.IOException; +import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; import java.util.concurrent.CountDownLatch; import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.AuthenticationStore; +import org.eclipse.jetty.client.util.BasicAuthentication; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.ssl.SslContextFactory; @@ -100,6 +103,9 @@ } else { theclient = new HttpClient(); } + AuthenticationStore authenticationStore = theclient.getAuthenticationStore(); + URI uri = URI.create(baseUrl); + authenticationStore.addAuthentication(new BasicAuthentication(uri, "thermostat", "agent", "agent-pwd")); theclient.start(); return theclient; }