AMBARI-18510. Use logsearch truststore to look for credential in case of external authentication (Miklos Gergely via oleewere)
Change-Id: I44bd04868d00574c339fd31c8303a7abf97686f6 Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/fb70f1b9 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/fb70f1b9 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/fb70f1b9 Branch: refs/heads/branch-dev-patch-upgrade Commit: fb70f1b93a7237f7d1e1a7889552fe9428fa0c7d Parents: 762abbc Author: Miklos Gergely <mgerg...@hortonworks.com> Authored: Mon Oct 3 16:14:54 2016 +0200 Committer: oleewere <oleew...@gmail.com> Committed: Sat Nov 5 16:08:55 2016 +0100 ---------------------------------------------------------------------- .../src/main/scripts/run.sh | 4 +- .../org/apache/ambari/logsearch/LogSearch.java | 32 +-- .../logsearch/common/ExternalServerClient.java | 24 +- .../logsearch/common/PropertiesHelper.java | 2 +- .../apache/ambari/logsearch/util/SSLUtil.java | 107 +++++++++ ...LogsearchAbstractAuthenticationProvider.java | 20 +- .../LogsearchAuthenticationProvider.java | 86 +++---- ...rchExternalServerAuthenticationProvider.java | 97 +++----- .../LogsearchFileAuthenticationProvider.java | 9 +- .../LogsearchSimpleAuthenticationProvider.java | 23 +- .../src/main/scripts/run.sh | 2 +- .../LogsearchAuthenticationProviderTest.java | 205 ++++++++++++++++ ...xternalServerAuthenticationProviderTest.java | 185 +++++++++++++++ ...LogsearchFileAuthenticationProviderTest.java | 231 +++++++++++++++++++ ...LogsearchLdapAuthenticationProviderTest.java | 61 +++++ ...gsearchSimpleAuthenticationProviderTest.java | 118 ++++++++++ .../src/test/resources/logsearch.properties | 3 +- ambari-logsearch/docker/.gitignore | 2 +- ambari-logsearch/docker/Dockerfile | 14 +- ambari-logsearch/docker/bin/start.sh | 57 ++++- ambari-logsearch/docker/logsearch-docker.sh | 6 +- .../test-config/logfeeder/logfeeder-env.sh | 13 +- .../test-config/logsearch/logsearch-env.sh | 12 +- .../logsearch/logsearch-https.properties | 55 +++++ .../docker/test-config/solr/solr-env-ssl.sh | 101 ++++++++ .../docker/test-config/solr/solr-env.sh | 4 +- .../0.1.0/properties/infra-solr-env.sh.j2 | 4 +- .../0.5.0/properties/logsearch-env.sh.j2 | 2 +- 28 files changed, 1256 insertions(+), 223 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-logfeeder/src/main/scripts/run.sh ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-logfeeder/src/main/scripts/run.sh b/ambari-logsearch/ambari-logsearch-logfeeder/src/main/scripts/run.sh index dfc7b7b..5aecd00 100644 --- a/ambari-logsearch/ambari-logsearch-logfeeder/src/main/scripts/run.sh +++ b/ambari-logsearch/ambari-logsearch-logfeeder/src/main/scripts/run.sh @@ -97,9 +97,9 @@ if [ $foreground -eq 0 ]; then echo "Starting logfeeder. Output file=$LOGFILE pid_file=$PID_FILE" #LOGFEEDER_CLI_CLASSPATH= #set -x - nohup $JAVA -cp "$LOGFEEDER_CLI_CLASSPATH:$LOGFEEDER_CONF_DIR:$script_dir/libs/*:$script_dir/classes:$script_dir/LogProcessor.jar" $LOGFEEDER_GC_OPTS $LOGFEEDER_JAVA_MEM $LOGFEEDER_JAVA_OPTS $JMX org.apache.ambari.logfeeder.LogFeeder $* > $LOGFILE 2>&1 & + nohup $JAVA -cp "$LOGFEEDER_CLI_CLASSPATH:$LOGFEEDER_CONF_DIR:$script_dir/libs/*:$script_dir/classes" $LOGFEEDER_GC_OPTS $LOGFEEDER_JAVA_MEM $LOGFEEDER_JAVA_OPTS $JMX org.apache.ambari.logfeeder.LogFeeder $* > $LOGFILE 2>&1 & echo $! > $PID_FILE else - $JAVA -cp "$LOGFEEDER_CLI_CLASSPATH:$LOGFEEDER_CONF_DIR:$script_dir/libs/*:$script_dir/classes:$script_dir/LogProcessor.jar" $LOGFEEDER_JAVA_MEM $LOGFEEDER_JAVA_OPTS $JMX org.apache.ambari.logfeeder.LogFeeder $* + $JAVA -cp "$LOGFEEDER_CLI_CLASSPATH:$LOGFEEDER_CONF_DIR:$script_dir/libs/*:$script_dir/classes" $LOGFEEDER_JAVA_MEM $LOGFEEDER_JAVA_OPTS $JMX org.apache.ambari.logfeeder.LogFeeder $* fi http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/LogSearch.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/LogSearch.java b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/LogSearch.java index 75d8be3..5a7cf02 100644 --- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/LogSearch.java +++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/LogSearch.java @@ -29,6 +29,7 @@ import java.util.EnumSet; import org.apache.ambari.logsearch.common.ManageStartEndTime; import org.apache.ambari.logsearch.common.PropertiesHelper; import org.apache.ambari.logsearch.conf.ApplicationConfig; +import org.apache.ambari.logsearch.util.SSLUtil; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.eclipse.jetty.server.Connector; @@ -56,15 +57,6 @@ import javax.servlet.DispatcherType; public class LogSearch { private static final Logger logger = Logger.getLogger(LogSearch.class); - private static final String KEYSTORE_LOCATION_ARG = "javax.net.ssl.keyStore"; - private static final String KEYSTORE_PASSWORD_ARG = "javax.net.ssl.keyStorePassword"; - private static final String KEYSTORE_TYPE_ARG = "javax.net.ssl.keyStoreType"; - private static final String DEFAULT_KEYSTORE_TYPE = "JKS"; - private static final String TRUSTSTORE_LOCATION_ARG = "javax.net.ssl.trustStore"; - private static final String TRUSTSTORE_PASSWORD_ARG = "javax.net.ssl.trustStorePassword"; - private static final String TRUSTSTORE_TYPE_ARG = "javax.net.ssl.trustStoreType"; - private static final String DEFAULT_TRUSTSTORE_TYPE = "JKS"; - private static final String LOGSEARCH_PROTOCOL_PROP = "logsearch.protocol"; private static final String HTTPS_PROTOCOL = "https"; private static final String HTTP_PROTOCOL = "http"; @@ -112,28 +104,13 @@ public class LogSearch { protcolProperty = HTTP_PROTOCOL; } String port = null; - String keystoreLocation = System.getProperty(KEYSTORE_LOCATION_ARG); - String keystorePassword = System.getProperty(KEYSTORE_PASSWORD_ARG); - String keystoreType = System.getProperty(KEYSTORE_TYPE_ARG,DEFAULT_KEYSTORE_TYPE); - String trustStoreLocation = System.getProperty(TRUSTSTORE_LOCATION_ARG); - String trustStorePassword = System.getProperty(TRUSTSTORE_PASSWORD_ARG); - String trustStoreType = System.getProperty(TRUSTSTORE_TYPE_ARG,DEFAULT_TRUSTSTORE_TYPE); - if (HTTPS_PROTOCOL.equals(protcolProperty) - && !StringUtils.isEmpty(keystoreLocation) && !StringUtils.isEmpty(keystorePassword)) { + if (HTTPS_PROTOCOL.equals(protcolProperty) && SSLUtil.isKeyStoreSpecified()) { logger.info("Building https server..........."); port = portSpecified ? argv[0] : HTTPS_PORT; checkPort(Integer.parseInt(port)); HttpConfiguration https = new HttpConfiguration(); https.addCustomizer(new SecureRequestCustomizer()); - SslContextFactory sslContextFactory = new SslContextFactory(); - sslContextFactory.setKeyStorePath(keystoreLocation); - sslContextFactory.setKeyStorePassword(keystorePassword); - sslContextFactory.setKeyStoreType(keystoreType); - if (!StringUtils.isEmpty(trustStoreLocation) && !StringUtils.isEmpty(trustStorePassword)) { - sslContextFactory.setTrustStorePath(trustStoreLocation); - sslContextFactory.setTrustStorePassword(trustStorePassword); - sslContextFactory.setTrustStoreType(trustStoreType); - } + SslContextFactory sslContextFactory = SSLUtil.getSslContextFactory(); ServerConnector sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"), new HttpConnectionFactory(https)); @@ -146,8 +123,7 @@ public class LogSearch { connector.setPort(Integer.parseInt(port)); server.setConnectors(new Connector[] { connector }); } - URI logsearchURI = URI.create(String.format("%s://0.0.0.0:%s", protcolProperty, - port)); + URI logsearchURI = URI.create(String.format("%s://0.0.0.0:%s", protcolProperty, port)); logger.info("Starting logsearch server URI=" + logsearchURI); return server; } http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/common/ExternalServerClient.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/common/ExternalServerClient.java b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/common/ExternalServerClient.java index c476b9d..1207373 100644 --- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/common/ExternalServerClient.java +++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/common/ExternalServerClient.java @@ -18,18 +18,14 @@ */ package org.apache.ambari.logsearch.common; -import java.util.List; -import java.util.Map; - import javax.inject.Inject; import javax.inject.Named; import javax.ws.rs.client.Invocation; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; import org.apache.ambari.logsearch.conf.AuthPropsConfig; -import org.apache.commons.lang.StringUtils; +import org.apache.ambari.logsearch.util.SSLUtil; import org.apache.log4j.Logger; import org.glassfish.jersey.client.JerseyClient; import org.glassfish.jersey.client.JerseyClientBuilder; @@ -42,10 +38,12 @@ import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; public class ExternalServerClient { private static Logger LOG = Logger.getLogger(ExternalServerClient.class); - private static final ThreadLocal<JerseyClient> localJerseyClient = new ThreadLocal<JerseyClient>(){ + private static final ThreadLocal<JerseyClient> localJerseyClient = new ThreadLocal<JerseyClient>() { @Override protected JerseyClient initialValue() { - return JerseyClientBuilder.createClient(); + return SSLUtil.isKeyStoreSpecified() ? + new JerseyClientBuilder().sslContext(SSLUtil.getSSLContext()).build() : + JerseyClientBuilder.createClient(); } }; @@ -55,10 +53,8 @@ public class ExternalServerClient { /** * Send GET request to an external server */ - public Object sendGETRequest(String url, Class klass, MultivaluedMap<String, String> queryParam, - String username, String password) - throws Exception { - url = authPropsConfig.getExternalAuthHostUrl() + url; + public Object sendGETRequest(String loginUrl, Class<?> klass, String username, String password) throws Exception { + String url = authPropsConfig.getExternalAuthHostUrl() + loginUrl; JerseyClient client = localJerseyClient.get(); HttpAuthenticationFeature authFeature = HttpAuthenticationFeature.basicBuilder() .credentials(username, password) @@ -67,11 +63,7 @@ public class ExternalServerClient { WebTarget target = client.target(url); LOG.debug("URL: " + url); - for (Map.Entry<String, List<String>> entry : queryParam.entrySet()) { - target = target.queryParam(entry.getKey(), entry.getValue()); - LOG.debug( - String.format("Query parameter: name - %s ; value - %s ;" + entry.getKey(), StringUtils.join(entry.getValue(),','))); - } + Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON_TYPE); try { return invocationBuilder.get().readEntity(klass); http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/common/PropertiesHelper.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/common/PropertiesHelper.java b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/common/PropertiesHelper.java index 1844d8f..257ae3c 100644 --- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/common/PropertiesHelper.java +++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/common/PropertiesHelper.java @@ -43,7 +43,7 @@ public class PropertiesHelper extends PropertyPlaceholderConfigurer { private PropertiesHelper() { } - static { + static { propertiesMap = new HashMap<String, String>(); Properties properties = new Properties(); URL fileCompleteUrl = Thread.currentThread().getContextClassLoader().getResource(LOGSEARCH_PROP_FILE); http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/util/SSLUtil.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/util/SSLUtil.java b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/util/SSLUtil.java new file mode 100644 index 0000000..206f793 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/util/SSLUtil.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ambari.logsearch.util; + +import javax.net.ssl.SSLContext; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +public class SSLUtil { + private static final Logger logger = Logger.getLogger(SSLUtil.class); + + private static final String KEYSTORE_LOCATION_ARG = "javax.net.ssl.keyStore"; + private static final String KEYSTORE_PASSWORD_ARG = "javax.net.ssl.keyStorePassword"; + private static final String KEYSTORE_TYPE_ARG = "javax.net.ssl.keyStoreType"; + private static final String DEFAULT_KEYSTORE_TYPE = "JKS"; + private static final String TRUSTSTORE_LOCATION_ARG = "javax.net.ssl.trustStore"; + private static final String TRUSTSTORE_PASSWORD_ARG = "javax.net.ssl.trustStorePassword"; + private static final String TRUSTSTORE_TYPE_ARG = "javax.net.ssl.trustStoreType"; + private static final String DEFAULT_TRUSTSTORE_TYPE = "JKS"; + + private SSLUtil() { + throw new UnsupportedOperationException(); + } + + public static String getKeyStoreLocation() { + return System.getProperty(KEYSTORE_LOCATION_ARG); + } + + public static String getKeyStorePassword() { + return System.getProperty(KEYSTORE_PASSWORD_ARG); + } + + public static String getKeyStoreType() { + return System.getProperty(KEYSTORE_TYPE_ARG, DEFAULT_KEYSTORE_TYPE); + } + + public static String getTrustStoreLocation() { + return System.getProperty(TRUSTSTORE_LOCATION_ARG); + } + + public static String getTrustStorePassword() { + return System.getProperty(TRUSTSTORE_PASSWORD_ARG); + } + + public static String getTrustStoreType() { + return System.getProperty(TRUSTSTORE_TYPE_ARG, DEFAULT_TRUSTSTORE_TYPE); + } + + public static boolean isKeyStoreSpecified() { + return StringUtils.isNotEmpty(getKeyStoreLocation()) && StringUtils.isNotEmpty(getKeyStorePassword()); + } + + private static boolean isTrustStoreSpecified() { + return StringUtils.isNotEmpty(getTrustStoreLocation()) && StringUtils.isNotEmpty(getTrustStorePassword()); + } + + public static SslContextFactory getSslContextFactory() { + SslContextFactory sslContextFactory = new SslContextFactory(); + sslContextFactory.setKeyStorePath(getKeyStoreLocation()); + sslContextFactory.setKeyStorePassword(getKeyStorePassword()); + sslContextFactory.setKeyStoreType(getKeyStoreType()); + if (isTrustStoreSpecified()) { + sslContextFactory.setTrustStorePath(getTrustStoreLocation()); + sslContextFactory.setTrustStorePassword(getTrustStorePassword()); + sslContextFactory.setTrustStoreType(getTrustStoreType()); + } + + return sslContextFactory; + } + + public static SSLContext getSSLContext() { + SslContextFactory sslContextFactory = getSslContextFactory(); + + try { + sslContextFactory.start(); + return sslContextFactory.getSslContext(); + } catch (Exception e) { + logger.error("Could not create SSL Context", e); + return null; + } finally { + try { + sslContextFactory.stop(); + } catch (Exception e) { + logger.error("Could not stop sslContextFactory", e); + } + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchAbstractAuthenticationProvider.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchAbstractAuthenticationProvider.java b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchAbstractAuthenticationProvider.java index eab33a1..eb6c9f1 100644 --- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchAbstractAuthenticationProvider.java +++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchAbstractAuthenticationProvider.java @@ -27,11 +27,11 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; -public abstract class LogsearchAbstractAuthenticationProvider implements AuthenticationProvider { +abstract class LogsearchAbstractAuthenticationProvider implements AuthenticationProvider { - public final static String AUTH_METHOD_PROP_START_WITH = "logsearch.auth."; + private static final String AUTH_METHOD_PROPERTY_PREFIX = "logsearch.auth."; - protected enum AUTH_METHOD { + protected enum AuthMethod { LDAP, FILE, EXTERNAL_AUTH, SIMPLE }; @@ -42,25 +42,19 @@ public abstract class LogsearchAbstractAuthenticationProvider implements Authent /** * GET Default GrantedAuthority - * - * @param username - * @return List<GrantedAuthority> */ - protected List<GrantedAuthority> getAuthorities(String username) { - final List<GrantedAuthority> grantedAuths = new ArrayList<>(); + protected List<GrantedAuthority> getAuthorities() { + List<GrantedAuthority> grantedAuths = new ArrayList<>(); grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER")); return grantedAuths; } /** * Check authentication provider is enable or disable for specified method - * - * @param method - * @return boolean */ - public boolean isEnable(AUTH_METHOD method) { + public boolean isEnable(AuthMethod method) { String methodName = method.name().toLowerCase(); - String property = AUTH_METHOD_PROP_START_WITH + methodName + ".enable"; + String property = AUTH_METHOD_PROPERTY_PREFIX + methodName + ".enable"; boolean isEnable = PropertiesHelper.getBooleanProperty(property, false); return isEnable; } http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchAuthenticationProvider.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchAuthenticationProvider.java b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchAuthenticationProvider.java index d37e545..711e3ec 100644 --- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchAuthenticationProvider.java +++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchAuthenticationProvider.java @@ -20,8 +20,8 @@ package org.apache.ambari.logsearch.web.security; import java.util.HashMap; -import org.apache.ambari.logsearch.dao.UserDao; import org.apache.ambari.logsearch.util.JSONUtil; +import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -32,15 +32,9 @@ import javax.inject.Inject; import javax.inject.Named; @Named -public class LogsearchAuthenticationProvider extends - LogsearchAbstractAuthenticationProvider { - private static final Logger logger = Logger - .getLogger(LogsearchAuthenticationProvider.class); - private static Logger auditLogger = Logger - .getLogger("org.apache.ambari.logsearch.audit"); - - @Inject - private UserDao userDao; +public class LogsearchAuthenticationProvider extends LogsearchAbstractAuthenticationProvider { + private static final Logger logger = Logger .getLogger(LogsearchAuthenticationProvider.class); + private static final Logger auditLogger = Logger.getLogger("org.apache.ambari.logsearch.audit"); @Inject private LogsearchLdapAuthenticationProvider ldapAuthenticationProvider; @@ -49,44 +43,40 @@ public class LogsearchAuthenticationProvider extends private LogsearchFileAuthenticationProvider fileAuthenticationProvider; @Inject - private LogsearchSimpleAuthenticationProvider simpleAuthenticationProvider; + private LogsearchExternalServerAuthenticationProvider externalServerAuthenticationProvider; @Inject - private LogsearchExternalServerAuthenticationProvider externalServerAuthenticationProvider; + private LogsearchSimpleAuthenticationProvider simpleAuthenticationProvider; @Override - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { - logger.info("Authenticating user:" + authentication.getName() - + ", userDetail=" + authentication.toString()); - Authentication inAuthentication = authentication; - AuthenticationException authException = null; + public Authentication authenticate(Authentication inAuthentication) throws AuthenticationException { + logger.info("Authenticating user:" + inAuthentication.getName() + ", userDetail=" + inAuthentication.toString()); + logger.info("authentication.class=" + inAuthentication.getClass().getName()); + HashMap<String, Object> auditRecord = new HashMap<String, Object>(); - auditRecord.put("user", authentication.getName()); - auditRecord.put("principal", authentication.getPrincipal().toString()); - auditRecord.put("auth_class", authentication.getClass().getName()); - logger.info("authentication.class=" - + authentication.getClass().getName()); + auditRecord.put("user", inAuthentication.getName()); + auditRecord.put("principal", inAuthentication.getPrincipal().toString()); + auditRecord.put("auth_class", inAuthentication.getClass().getName()); if (inAuthentication instanceof UsernamePasswordAuthenticationToken) { UsernamePasswordAuthenticationToken authClass = (UsernamePasswordAuthenticationToken) inAuthentication; Object details = authClass.getDetails(); if (details instanceof WebAuthenticationDetails) { WebAuthenticationDetails webAuthentication = (WebAuthenticationDetails) details; - auditRecord.put("remote_ip", - webAuthentication.getRemoteAddress()); + auditRecord.put("remote_ip", webAuthentication.getRemoteAddress()); auditRecord.put("session", webAuthentication.getSessionId()); } } + boolean isSuccess = false; try { - for (AUTH_METHOD authMethod : AUTH_METHOD.values()) { + Authentication authentication = inAuthentication; + AuthenticationException authException = null; + + for (AuthMethod authMethod : AuthMethod.values()) { try { authentication = doAuth(authentication, authMethod); - if (authentication != null - && authentication.isAuthenticated()) { - logger.info("Authenticated using method=" - + authMethod.name() + ", user=" - + authentication.getName()); + if (authentication != null && authentication.isAuthenticated()) { + logger.info("Authenticated using method=" + authMethod.name() + ", user=" + authentication.getName()); auditRecord.put("result", "allowed"); isSuccess = true; auditRecord.put("authType", authMethod.name()); @@ -94,17 +84,15 @@ public class LogsearchAuthenticationProvider extends } } catch (AuthenticationException ex) { if (authException == null) { - // Let's save the first one authException = ex; } - }catch(Exception e){ - logger.error(e,e.getCause()); + } catch (Exception e) { + logger.error(e, e.getCause()); } } + auditRecord.put("result", "denied"); - logger.warn("Authentication failed for user=" - + inAuthentication.getName() + ", userDetail=" - + inAuthentication.toString()); + logger.warn("Authentication failed for user=" + inAuthentication.getName() + ", userDetail=" + inAuthentication.toString()); if (authException != null) { auditRecord.put("reason", authException.getMessage()); throw authException; @@ -112,25 +100,17 @@ public class LogsearchAuthenticationProvider extends return authentication; } finally { String jsonStr = JSONUtil.mapToJSON(auditRecord); - if (isSuccess) { - auditLogger.info(jsonStr); - } else { - auditLogger.warn(jsonStr); - } + auditLogger.log(isSuccess ? Level.INFO : Level.WARN, jsonStr); } } - public Authentication doAuth(Authentication authentication, AUTH_METHOD authMethod) { - if (authMethod.equals(AUTH_METHOD.LDAP)) { - authentication = ldapAuthenticationProvider.authenticate(authentication); - } else if (authMethod.equals(AUTH_METHOD.FILE)) { - authentication = fileAuthenticationProvider.authenticate(authentication); - } else if (authMethod.equals(AUTH_METHOD.SIMPLE)) { - authentication = simpleAuthenticationProvider.authenticate(authentication); - } else if (authMethod.equals(AUTH_METHOD.EXTERNAL_AUTH)) { - authentication = externalServerAuthenticationProvider.authenticate(authentication); - } else { - logger.error("Invalid authentication method :" + authMethod.name()); + private Authentication doAuth(Authentication authentication, AuthMethod authMethod) { + switch (authMethod) { + case LDAP: return ldapAuthenticationProvider.authenticate(authentication); + case FILE: return fileAuthenticationProvider.authenticate(authentication); + case EXTERNAL_AUTH: return externalServerAuthenticationProvider.authenticate(authentication); + case SIMPLE: return simpleAuthenticationProvider.authenticate(authentication); + default: logger.error("Invalid authentication method :" + authMethod.name()); } return authentication; } http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchExternalServerAuthenticationProvider.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchExternalServerAuthenticationProvider.java b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchExternalServerAuthenticationProvider.java index 7e146ac..e23f0a2 100644 --- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchExternalServerAuthenticationProvider.java +++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchExternalServerAuthenticationProvider.java @@ -42,57 +42,30 @@ import org.springframework.security.core.AuthenticationException; * call */ @Named -public class LogsearchExternalServerAuthenticationProvider extends - LogsearchAbstractAuthenticationProvider { +public class LogsearchExternalServerAuthenticationProvider extends LogsearchAbstractAuthenticationProvider { - private static Logger LOG = Logger - .getLogger(LogsearchExternalServerAuthenticationProvider.class); + private static Logger LOG = Logger.getLogger(LogsearchExternalServerAuthenticationProvider.class); - public final static String ALLOWED_ROLE_PROP = "logsearch.roles.allowed"; + private static final String ALLOWED_ROLE_PROP = "logsearch.roles.allowed"; - public static enum PRIVILEGE_INFO { - PERMISSION_LABEL { - @Override - public String toString() { - return "permission_label"; - } - }, - PERMISSION_NAME { - @Override - public String toString() { - return "permission_name"; - } - }, - PRINCIPAL_NAME { - @Override - public String toString() { - return "principal_name"; - } - }, - PRINCIPAL_TYPE { - @Override - public String toString() { - return "principal_type"; - } - }, - PRIVILEGE_ID { - @Override - public String toString() { - return "privilege_id"; - } - }, - TYPE { - @Override - public String toString() { - return "type"; - } - }, - USER_NAME { - @Override - public String toString() { - return "user_name"; - } - }; + private static enum PrivilegeInfo { + PERMISSION_LABEL("permission_label"), + PERMISSION_NAME("permission_name"), + PRINCIPAL_NAME("principal_name"), + PRINCIPAL_TYPE("principal_type"), + PRIVILEGE_ID("privilege_id"), + TYPE("type"), + USER_NAME("user_name"); + + private String propertyKey; + + private PrivilegeInfo(String name) { + this.propertyKey = name; + } + + public String toString() { + return propertyKey; + } } @Inject @@ -104,19 +77,17 @@ public class LogsearchExternalServerAuthenticationProvider extends /** * Authenticating user from external-server using REST call * - * @param authentication - * the authentication request object. + * @param authentication the authentication request object. * @return a fully authenticated object including credentials. - * @throws AuthenticationException - * if authentication fails. + * @throws AuthenticationException if authentication fails. */ @Override - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!authPropsConfig.isAuthExternalEnabled()) { LOG.debug("external server auth is disabled."); return authentication; } + String username = authentication.getName(); String password = (String) authentication.getCredentials(); if (StringUtils.isBlank(username)) { @@ -125,38 +96,32 @@ public class LogsearchExternalServerAuthenticationProvider extends if (StringUtils.isBlank(password)) { throw new BadCredentialsException("Password can't be null or empty."); } - // html unescape password = StringEscapeUtils.unescapeHtml(password); username = StringEscapeUtils.unescapeHtml(username); + try { String finalLoginUrl = authPropsConfig.getExternalAuthLoginUrl().replace("$USERNAME", username); - String responseObj = (String) externalServerClient.sendGETRequest( - finalLoginUrl, String.class, null, username, password); + String responseObj = (String) externalServerClient.sendGETRequest(finalLoginUrl, String.class, username, password); if (!isAllowedRole(responseObj)) { - LOG.error(username + " does'nt have permission"); + LOG.error(username + " doesn't have permission"); throw new BadCredentialsException("Invalid User"); } - } catch (Exception e) { - LOG.error("Login failed for username :" + username + " Error :" - + e.getLocalizedMessage()); + LOG.error("Login failed for username :" + username + " Error :" + e.getLocalizedMessage()); throw new BadCredentialsException("Bad credentials"); } - authentication = new UsernamePasswordAuthenticationToken(username, - password, getAuthorities(username)); + authentication = new UsernamePasswordAuthenticationToken(username, password, getAuthorities()); return authentication; } /** * Return true/false based on PEMISSION NAME return boolean */ - @SuppressWarnings("static-access") private boolean isAllowedRole(String responseJson) { String allowedRoleList[] = PropertiesHelper.getPropertyStringList(ALLOWED_ROLE_PROP); List<String> values = new ArrayList<>(); - JSONUtil.getValuesOfKey(responseJson, - PRIVILEGE_INFO.PERMISSION_NAME.toString(), values); + JSONUtil.getValuesOfKey(responseJson, PrivilegeInfo.PERMISSION_NAME.toString(), values); if (values.isEmpty()) return true; http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchFileAuthenticationProvider.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchFileAuthenticationProvider.java b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchFileAuthenticationProvider.java index 51b3547..8c12e0a 100644 --- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchFileAuthenticationProvider.java +++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchFileAuthenticationProvider.java @@ -39,7 +39,7 @@ import javax.inject.Named; @Named public class LogsearchFileAuthenticationProvider extends LogsearchAbstractAuthenticationProvider { - private static Logger logger = Logger.getLogger(LogsearchFileAuthenticationProvider.class); + private static final Logger logger = Logger.getLogger(LogsearchFileAuthenticationProvider.class); @Inject private AuthPropsConfig authPropsConfig; @@ -53,6 +53,7 @@ public class LogsearchFileAuthenticationProvider extends LogsearchAbstractAuthen logger.debug("File auth is disabled."); return authentication; } + String username = authentication.getName(); String password = (String) authentication.getCredentials(); if (StringUtils.isBlank(username)) { @@ -70,16 +71,16 @@ public class LogsearchFileAuthenticationProvider extends LogsearchAbstractAuthen logger.error("Username not found."); throw new BadCredentialsException("User not found."); } - if (password == null || password.isEmpty()) { + if (StringUtils.isEmpty(user.getPassword())) { logger.error("Password can't be null or empty."); throw new BadCredentialsException("Password can't be null or empty."); } - String encPassword = CommonUtil.encryptPassword(username, password); if (!encPassword.equals(user.getPassword())) { logger.error("Wrong password for user=" + username); - throw new BadCredentialsException("Wrong password"); + throw new BadCredentialsException("Wrong password."); } + Collection<? extends GrantedAuthority> authorities = user.getAuthorities(); authentication = new UsernamePasswordAuthenticationToken(username, encPassword, authorities); return authentication; http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchSimpleAuthenticationProvider.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchSimpleAuthenticationProvider.java b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchSimpleAuthenticationProvider.java index 400361b..92a7aaa 100644 --- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchSimpleAuthenticationProvider.java +++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/security/LogsearchSimpleAuthenticationProvider.java @@ -34,7 +34,7 @@ import javax.inject.Named; @Named public class LogsearchSimpleAuthenticationProvider extends LogsearchAbstractAuthenticationProvider { - private static Logger logger = Logger.getLogger(LogsearchSimpleAuthenticationProvider.class); + private static final Logger logger = Logger.getLogger(LogsearchSimpleAuthenticationProvider.class); @Inject private AuthPropsConfig authPropsConfig; @@ -45,29 +45,28 @@ public class LogsearchSimpleAuthenticationProvider extends LogsearchAbstractAuth logger.debug("Simple auth is disabled"); return authentication; } + String username = authentication.getName(); String password = (String) authentication.getCredentials(); username = StringEscapeUtils.unescapeHtml(username); if (StringUtils.isBlank(username)) { throw new BadCredentialsException("Username can't be null or empty."); } + User user = new User(); user.setUsername(username); - authentication = new UsernamePasswordAuthenticationToken(username, password, getAuthorities(username)); + authentication = new UsernamePasswordAuthenticationToken(username, password, getAuthorities()); return authentication; } @Override - public boolean isEnable(AUTH_METHOD method) { - boolean ldapEnabled = super.isEnable(AUTH_METHOD.LDAP); - boolean fileEnabled = super.isEnable(AUTH_METHOD.FILE); - boolean externalAuthEnabled = super.isEnable(AUTH_METHOD.EXTERNAL_AUTH); + public boolean isEnable(AuthMethod method) { + boolean ldapEnabled = super.isEnable(AuthMethod.LDAP); + boolean fileEnabled = super.isEnable(AuthMethod.FILE); + boolean externalAuthEnabled = super.isEnable(AuthMethod.EXTERNAL_AUTH); boolean simpleEnabled = super.isEnable(method); - if (!ldapEnabled && !fileEnabled && simpleEnabled && !externalAuthEnabled) { - // simple is enabled only when rest three are disabled and simple is enable - return true; - } else { - return false; - } + + // simple is enabled only when rest three are disabled and simple is enable + return !ldapEnabled && !fileEnabled && !externalAuthEnabled && simpleEnabled; } } http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/main/scripts/run.sh ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/scripts/run.sh b/ambari-logsearch/ambari-logsearch-portal/src/main/scripts/run.sh index 4e8901d..1204ef3 100755 --- a/ambari-logsearch/ambari-logsearch-portal/src/main/scripts/run.sh +++ b/ambari-logsearch/ambari-logsearch-portal/src/main/scripts/run.sh @@ -96,5 +96,5 @@ LOGSEARCH_GC_OPTS="-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:$LOGSEARCH echo "Starting logsearch. Output file=$LOGFILE pid_file=$PID_FILE" #LOGSEARCH_CLI_CLASSPATH= #set -x -nohup $JAVA -cp "$LOGSEARCH_CLI_CLASSPATH:$LOGSEARCH_CONF_DIR:$script_dir/libs/*:$script_dir/classes:$script_dir/LogProcessor.jar" $LOGSEARCH_GC_OPTS $LOGSEARCH_JAVA_MEM $LOGSEARCH_JAVA_OPTS $JMX org.apache.ambari.logsearch.LogSearch $LOGSEARCH_PORT $* > $LOGFILE 2>&1 & +nohup $JAVA -cp "$LOGSEARCH_CLI_CLASSPATH:$LOGSEARCH_CONF_DIR:$script_dir/libs/*:$script_dir/classes" $LOGSEARCH_GC_OPTS $LOGSEARCH_JAVA_MEM $LOGSEARCH_JAVA_OPTS $JMX org.apache.ambari.logsearch.LogSearch $LOGSEARCH_PORT $* > $LOGFILE 2>&1 & echo $! > $PID_FILE http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchAuthenticationProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchAuthenticationProviderTest.java b/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchAuthenticationProviderTest.java new file mode 100644 index 0000000..c6a5ba5 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchAuthenticationProviderTest.java @@ -0,0 +1,205 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.ambari.logsearch.web.security; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertSame; +import static junit.framework.Assert.assertTrue; +import static org.easymock.EasyMock.strictMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import java.lang.reflect.Field; + +public class LogsearchAuthenticationProviderTest { + private static final Authentication SUCCESSFUL_AUTHENTICATION = new TestingAuthenticationToken("principal", "credentials"); + private static final Authentication FAILED_AUTHENTICATION = new TestingAuthenticationToken("principal", "credentials"); + static { + SUCCESSFUL_AUTHENTICATION.setAuthenticated(true); + FAILED_AUTHENTICATION.setAuthenticated(false); + } + + private LogsearchAuthenticationProvider provider; + + private LogsearchLdapAuthenticationProvider mockLdapProvider; + private LogsearchFileAuthenticationProvider mockFileProvider; + private LogsearchExternalServerAuthenticationProvider mockExternalServerProvider; + private LogsearchSimpleAuthenticationProvider mockSimpleProvider; + + @Before + public void resetContext() throws Exception { + provider = new LogsearchAuthenticationProvider(); + + mockLdapProvider = strictMock(LogsearchLdapAuthenticationProvider.class); + mockFileProvider = strictMock(LogsearchFileAuthenticationProvider.class); + mockExternalServerProvider = strictMock(LogsearchExternalServerAuthenticationProvider.class); + mockSimpleProvider = strictMock(LogsearchSimpleAuthenticationProvider.class); + + Field ldapProviderField = LogsearchAuthenticationProvider.class.getDeclaredField("ldapAuthenticationProvider"); + ldapProviderField.setAccessible(true); + ldapProviderField.set(provider, mockLdapProvider); + + Field fileProviderField = LogsearchAuthenticationProvider.class.getDeclaredField("fileAuthenticationProvider"); + fileProviderField.setAccessible(true); + fileProviderField.set(provider, mockFileProvider); + + Field extarnalProviderField = LogsearchAuthenticationProvider.class.getDeclaredField("externalServerAuthenticationProvider"); + extarnalProviderField.setAccessible(true); + extarnalProviderField.set(provider, mockExternalServerProvider); + + Field simpleProviderField = LogsearchAuthenticationProvider.class.getDeclaredField("simpleAuthenticationProvider"); + simpleProviderField.setAccessible(true); + simpleProviderField.set(provider, mockSimpleProvider); + } + + @Test + public void testLdapAuthenticates() { + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + expect(mockLdapProvider.authenticate(authentication)).andReturn(SUCCESSFUL_AUTHENTICATION); + + replay(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + + Authentication authenticationResult = provider.authenticate(authentication); + assertSame(authenticationResult, SUCCESSFUL_AUTHENTICATION); + + verify(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + } + + @Test + public void testFileAuthenticates() { + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + expect(mockLdapProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockFileProvider.authenticate(authentication)).andReturn(SUCCESSFUL_AUTHENTICATION); + + replay(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + + Authentication authenticationResult = provider.authenticate(authentication); + assertSame(authenticationResult, SUCCESSFUL_AUTHENTICATION); + + verify(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + } + + @Test + public void testExternalAuthenticates() { + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + expect(mockLdapProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockFileProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockExternalServerProvider.authenticate(authentication)).andReturn(SUCCESSFUL_AUTHENTICATION); + + replay(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + + Authentication authenticationResult = provider.authenticate(authentication); + assertSame(authenticationResult, SUCCESSFUL_AUTHENTICATION); + + verify(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + } + + @Test + public void testSimpleAuthenticates() { + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + expect(mockLdapProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockFileProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockExternalServerProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockSimpleProvider.authenticate(authentication)).andReturn(SUCCESSFUL_AUTHENTICATION); + + replay(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + + Authentication authenticationResult = provider.authenticate(authentication); + assertSame(authenticationResult, SUCCESSFUL_AUTHENTICATION); + + verify(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + } + + @Test + public void testNoOneAuthenticates() { + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + expect(mockLdapProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockFileProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockExternalServerProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockSimpleProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + + replay(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + + Authentication authenticationResult = provider.authenticate(authentication); + assertSame(authenticationResult, FAILED_AUTHENTICATION); + + verify(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + } + + @Test + public void testOneExceptionAndAuthenticates() { + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + expect(mockLdapProvider.authenticate(authentication)).andThrow(new AuthenticationException("") {}); + expect(mockFileProvider.authenticate(authentication)).andReturn(SUCCESSFUL_AUTHENTICATION); + + replay(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + + Authentication authenticationResult = provider.authenticate(authentication); + assertSame(authenticationResult, SUCCESSFUL_AUTHENTICATION); + + verify(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + } + + @Test + public void testOneExceptionNoOneAuthenticates() { + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + expect(mockLdapProvider.authenticate(authentication)).andThrow(new AuthenticationException("msg1") {}); + expect(mockFileProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockExternalServerProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockSimpleProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + + replay(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown AuthenticationException", false); + } catch(AuthenticationException e) { + assertEquals(e.getMessage(), "msg1"); + } + + verify(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + } + + @Test + public void testTwoExceptionNoOneAuthenticates() { + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + expect(mockLdapProvider.authenticate(authentication)).andThrow(new AuthenticationException("msg1") {}); + expect(mockFileProvider.authenticate(authentication)).andThrow(new AuthenticationException("msg2") {}); + expect(mockExternalServerProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + expect(mockSimpleProvider.authenticate(authentication)).andReturn(FAILED_AUTHENTICATION); + + replay(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown AuthenticationException", false); + } catch(AuthenticationException e) { + assertEquals(e.getMessage(), "msg1"); + } + + verify(mockLdapProvider, mockFileProvider, mockSimpleProvider, mockExternalServerProvider); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchExternalServerAuthenticationProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchExternalServerAuthenticationProviderTest.java b/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchExternalServerAuthenticationProviderTest.java new file mode 100644 index 0000000..d6247a1 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchExternalServerAuthenticationProviderTest.java @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.ambari.logsearch.web.security; + +import org.apache.ambari.logsearch.common.ExternalServerClient; +import org.apache.ambari.logsearch.conf.AuthPropsConfig; +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertSame; +import static junit.framework.Assert.assertTrue; +import static org.easymock.EasyMock.strictMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import java.lang.reflect.Field; + +public class LogsearchExternalServerAuthenticationProviderTest { + + private LogsearchExternalServerAuthenticationProvider provider; + private AuthPropsConfig mockAuthPropsConfig; + private ExternalServerClient mockExternalServerClient; + + @Before + public void init() throws Exception { + provider = new LogsearchExternalServerAuthenticationProvider(); + mockAuthPropsConfig = strictMock(AuthPropsConfig.class); + mockExternalServerClient = strictMock(ExternalServerClient.class); + + Field authPropsConfigField = LogsearchExternalServerAuthenticationProvider.class.getDeclaredField("authPropsConfig"); + authPropsConfigField.setAccessible(true); + authPropsConfigField.set(provider, mockAuthPropsConfig); + + Field externalServerClientField = LogsearchExternalServerAuthenticationProvider.class.getDeclaredField("externalServerClient"); + externalServerClientField.setAccessible(true); + externalServerClientField.set(provider, mockExternalServerClient); + } + + @Test + public void testAuthenticationDisabled() { + expect(mockAuthPropsConfig.isAuthExternalEnabled()).andReturn(false); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + assertSame(provider.authenticate(authentication), authentication); + + verify(mockAuthPropsConfig); + } + + @Test + public void testAuthenticationEmptyUser() { + expect(mockAuthPropsConfig.isAuthExternalEnabled()).andReturn(true); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("", "credentials"); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch(BadCredentialsException e) { + assertEquals("Username can't be null or empty.", e.getMessage()); + } + + verify(mockAuthPropsConfig); + } + + @Test + public void testAuthenticationNullUser() { + expect(mockAuthPropsConfig.isAuthExternalEnabled()).andReturn(true); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken(null, "credentials"); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch(BadCredentialsException e) { + assertEquals("Username can't be null or empty.", e.getMessage()); + } + + verify(mockAuthPropsConfig); + } + + + @Test + public void testAuthenticationEmptyPassword() { + expect(mockAuthPropsConfig.isAuthExternalEnabled()).andReturn(true); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("principal", ""); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch(BadCredentialsException e) { + assertEquals("Password can't be null or empty.", e.getMessage()); + } + + verify(mockAuthPropsConfig); + } + + @Test + public void testAuthenticationNullPassword() { + expect(mockAuthPropsConfig.isAuthExternalEnabled()).andReturn(true); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("principal", null); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch(BadCredentialsException e) { + assertEquals("Password can't be null or empty.", e.getMessage()); + } + + verify(mockAuthPropsConfig); + } + + @Test + public void testAuthenticationUnsuccessful() throws Exception { + expect(mockAuthPropsConfig.isAuthExternalEnabled()).andReturn(true); + expect(mockAuthPropsConfig.getExternalAuthLoginUrl()).andReturn("http://server.com?userName=$USERNAME"); + expect(mockExternalServerClient.sendGETRequest("http://server.com?userName=principal", String.class, "principal", "credentials")) + .andReturn("{\"permission_name\": \"NOT.AMBARI.ADMINISTRATOR\" }"); + + replay(mockAuthPropsConfig, mockExternalServerClient); + + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch (BadCredentialsException e) { + assertEquals("Bad credentials", e.getMessage()); + } + + verify(mockAuthPropsConfig, mockExternalServerClient); + } + + @Test + public void testAuthenticationSuccessful() throws Exception { + expect(mockAuthPropsConfig.isAuthExternalEnabled()).andReturn(true); + expect(mockAuthPropsConfig.getExternalAuthLoginUrl()).andReturn("http://server.com?userName=$USERNAME"); + expect(mockExternalServerClient.sendGETRequest("http://server.com?userName=principal", String.class, "principal", "credentials")) + .andReturn("{\"permission_name\": \"AMBARI.ADMINISTRATOR\" }"); + + replay(mockAuthPropsConfig, mockExternalServerClient); + + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + Authentication authenticationResult = provider.authenticate(authentication); + + assertEquals("principal", authenticationResult.getName()); + assertEquals("credentials", authenticationResult.getCredentials()); + assertEquals(1, authenticationResult.getAuthorities().size()); + assertEquals(new SimpleGrantedAuthority("ROLE_USER"), authenticationResult.getAuthorities().iterator().next()); + + verify(mockAuthPropsConfig, mockExternalServerClient); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchFileAuthenticationProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchFileAuthenticationProviderTest.java b/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchFileAuthenticationProviderTest.java new file mode 100644 index 0000000..407cc83 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchFileAuthenticationProviderTest.java @@ -0,0 +1,231 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.ambari.logsearch.web.security; + +import org.apache.ambari.logsearch.conf.AuthPropsConfig; +import org.apache.ambari.logsearch.util.CommonUtil; +import org.apache.ambari.logsearch.web.model.User; +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetailsService; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertSame; +import static junit.framework.Assert.assertTrue; +import static org.easymock.EasyMock.strictMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; + +public class LogsearchFileAuthenticationProviderTest { + + private LogsearchFileAuthenticationProvider provider; + private AuthPropsConfig mockAuthPropsConfig; + private UserDetailsService mockUserDetailsService; + + @Before + public void init() throws Exception { + provider = new LogsearchFileAuthenticationProvider(); + mockAuthPropsConfig = strictMock(AuthPropsConfig.class); + mockUserDetailsService = strictMock(UserDetailsService.class); + + Field authPropsConfigField = LogsearchFileAuthenticationProvider.class.getDeclaredField("authPropsConfig"); + authPropsConfigField.setAccessible(true); + authPropsConfigField.set(provider, mockAuthPropsConfig); + + Field userDetailsServiceField = LogsearchFileAuthenticationProvider.class.getDeclaredField("userDetailsService"); + userDetailsServiceField.setAccessible(true); + userDetailsServiceField.set(provider, mockUserDetailsService); + } + + @Test + public void testAuthenticationDisabled() { + expect(mockAuthPropsConfig.isAuthFileEnabled()).andReturn(false); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + assertSame(provider.authenticate(authentication), authentication); + + verify(mockAuthPropsConfig); + } + + @Test + public void testAuthenticationEmptyUser() { + expect(mockAuthPropsConfig.isAuthFileEnabled()).andReturn(true); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("", "credentials"); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch(BadCredentialsException e) { + assertEquals("Username can't be null or empty.", e.getMessage()); + } + + verify(mockAuthPropsConfig); + } + + @Test + public void testAuthenticationNullUser() { + expect(mockAuthPropsConfig.isAuthFileEnabled()).andReturn(true); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken(null, "credentials"); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch(BadCredentialsException e) { + assertEquals("Username can't be null or empty.", e.getMessage()); + } + + verify(mockAuthPropsConfig); + } + + + @Test + public void testAuthenticationEmptyPassword() { + expect(mockAuthPropsConfig.isAuthFileEnabled()).andReturn(true); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("principal", ""); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch(BadCredentialsException e) { + assertEquals("Password can't be null or empty.", e.getMessage()); + } + + verify(mockAuthPropsConfig); + } + + @Test + public void testAuthenticationNullPassword() { + expect(mockAuthPropsConfig.isAuthFileEnabled()).andReturn(true); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("principal", null); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch(BadCredentialsException e) { + assertEquals("Password can't be null or empty.", e.getMessage()); + } + + verify(mockAuthPropsConfig); + } + + @Test + public void testAuthenticationUnknownUser() { + expect(mockAuthPropsConfig.isAuthFileEnabled()).andReturn(true); + expect(mockUserDetailsService.loadUserByUsername("principal")).andReturn(null); + + replay(mockAuthPropsConfig, mockUserDetailsService); + + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch (BadCredentialsException e) { + assertEquals("User not found.", e.getMessage()); + } + + verify(mockAuthPropsConfig, mockUserDetailsService); + } + + @Test + public void testAuthenticationNoPassword() { + List<GrantedAuthority> grantedAuths = Arrays.<GrantedAuthority>asList(new SimpleGrantedAuthority("ROLE_USER")); + User user = new User("principal", null, grantedAuths); + + expect(mockAuthPropsConfig.isAuthFileEnabled()).andReturn(true); + expect(mockUserDetailsService.loadUserByUsername("principal")).andReturn(user); + + replay(mockAuthPropsConfig, mockUserDetailsService); + + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch (BadCredentialsException e) { + assertEquals("Password can't be null or empty.", e.getMessage()); + } + + verify(mockAuthPropsConfig, mockUserDetailsService); + } + + @Test + public void testAuthenticationWrongPassword() { + List<GrantedAuthority> grantedAuths = Arrays.<GrantedAuthority>asList(new SimpleGrantedAuthority("ROLE_USER")); + User user = new User("principal", CommonUtil.encryptPassword("principal", "notCredentials"), grantedAuths); + + expect(mockAuthPropsConfig.isAuthFileEnabled()).andReturn(true); + expect(mockUserDetailsService.loadUserByUsername("principal")).andReturn(user); + + replay(mockAuthPropsConfig, mockUserDetailsService); + + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch (BadCredentialsException e) { + assertEquals("Wrong password.", e.getMessage()); + } + + verify(mockAuthPropsConfig, mockUserDetailsService); + } + + @Test + public void testAuthenticationSuccessful() { + List<GrantedAuthority> grantedAuths = Arrays.<GrantedAuthority>asList(new SimpleGrantedAuthority("ROLE_USER")); + User user = new User("principal", CommonUtil.encryptPassword("principal", "credentials"), grantedAuths); + + expect(mockAuthPropsConfig.isAuthFileEnabled()).andReturn(true); + expect(mockUserDetailsService.loadUserByUsername("principal")).andReturn(user); + + replay(mockAuthPropsConfig, mockUserDetailsService); + + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + + Authentication authenticationResult = provider.authenticate(authentication); + assertEquals("principal", authenticationResult.getName()); + assertEquals(CommonUtil.encryptPassword("principal", "credentials"), authenticationResult.getCredentials()); + assertEquals(1, authenticationResult.getAuthorities().size()); + assertEquals(new SimpleGrantedAuthority("ROLE_USER"), authenticationResult.getAuthorities().iterator().next()); + + verify(mockAuthPropsConfig, mockUserDetailsService); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchLdapAuthenticationProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchLdapAuthenticationProviderTest.java b/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchLdapAuthenticationProviderTest.java new file mode 100644 index 0000000..c6af3e2 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchLdapAuthenticationProviderTest.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.ambari.logsearch.web.security; + +import org.apache.ambari.logsearch.conf.AuthPropsConfig; +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.Authentication; + +import static junit.framework.Assert.assertSame; +import static org.easymock.EasyMock.strictMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import java.lang.reflect.Field; + +public class LogsearchLdapAuthenticationProviderTest { + + private LogsearchLdapAuthenticationProvider provider; + private AuthPropsConfig mockAuthPropsConfig; + + @Before + public void init() throws Exception { + provider = new LogsearchLdapAuthenticationProvider(); + mockAuthPropsConfig = strictMock(AuthPropsConfig.class); + + Field f = LogsearchLdapAuthenticationProvider.class.getDeclaredField("authPropsConfig"); + f.setAccessible(true); + f.set(provider, mockAuthPropsConfig); + } + + @Test + public void testAuthenticationDisabled() { + expect(mockAuthPropsConfig.isAuthLdapEnabled()).andReturn(false); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + assertSame(provider.authenticate(authentication), authentication); + + verify(mockAuthPropsConfig); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchSimpleAuthenticationProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchSimpleAuthenticationProviderTest.java b/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchSimpleAuthenticationProviderTest.java new file mode 100644 index 0000000..7287012 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-portal/src/test/java/org/apache/ambari/logsearch/web/security/LogsearchSimpleAuthenticationProviderTest.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.ambari.logsearch.web.security; + +import org.apache.ambari.logsearch.conf.AuthPropsConfig; +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertSame; +import static junit.framework.Assert.assertTrue; +import static org.easymock.EasyMock.strictMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import java.lang.reflect.Field; + +public class LogsearchSimpleAuthenticationProviderTest { + + private LogsearchSimpleAuthenticationProvider provider; + private AuthPropsConfig mockAuthPropsConfig; + + @Before + public void init() throws Exception { + provider = new LogsearchSimpleAuthenticationProvider(); + mockAuthPropsConfig = strictMock(AuthPropsConfig.class); + + Field f = LogsearchSimpleAuthenticationProvider.class.getDeclaredField("authPropsConfig"); + f.setAccessible(true); + f.set(provider, mockAuthPropsConfig); + } + + @Test + public void testAuthenticationDisabled() { + expect(mockAuthPropsConfig.isAuthSimpleEnabled()).andReturn(false); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + assertSame(provider.authenticate(authentication), authentication); + + verify(mockAuthPropsConfig); + } + + @Test + public void testAuthenticationEmptyUser() { + expect(mockAuthPropsConfig.isAuthSimpleEnabled()).andReturn(true); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("", "credentials"); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch(BadCredentialsException e) { + assertEquals("Username can't be null or empty.", e.getMessage()); + } + + verify(mockAuthPropsConfig); + } + + @Test + public void testAuthenticationNullUser() { + expect(mockAuthPropsConfig.isAuthSimpleEnabled()).andReturn(true); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken(null, "credentials"); + + try { + provider.authenticate(authentication); + assertTrue("Should have thrown BadCredentialsException", false); + } catch(BadCredentialsException e) { + assertEquals("Username can't be null or empty.", e.getMessage()); + } + + verify(mockAuthPropsConfig); + } + + @Test + public void testAuthenticationSuccessful() { + expect(mockAuthPropsConfig.isAuthSimpleEnabled()).andReturn(true); + + replay(mockAuthPropsConfig); + + Authentication authentication = new TestingAuthenticationToken("principal", "credentials"); + + Authentication authenticationResult = provider.authenticate(authentication); + assertEquals("principal", authenticationResult.getName()); + assertEquals("credentials", authenticationResult.getCredentials()); + assertEquals(1, authenticationResult.getAuthorities().size()); + assertEquals(new SimpleGrantedAuthority("ROLE_USER"), authenticationResult.getAuthorities().iterator().next()); + + verify(mockAuthPropsConfig); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/ambari-logsearch-portal/src/test/resources/logsearch.properties ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-portal/src/test/resources/logsearch.properties b/ambari-logsearch/ambari-logsearch-portal/src/test/resources/logsearch.properties index fa3efb8..2715d1f 100755 --- a/ambari-logsearch/ambari-logsearch-portal/src/test/resources/logsearch.properties +++ b/ambari-logsearch/ambari-logsearch-portal/src/test/resources/logsearch.properties @@ -29,4 +29,5 @@ logsearch.collection.history.replication.factor=234 logsearch.solr.collection.history=test_history_logs_collection logsearch.auth.file.enable=true -logsearch.login.credentials.file=user_pass.json \ No newline at end of file +logsearch.login.credentials.file=user_pass.json +logsearch.roles.allowed=AMBARI.ADMINISTRATOR http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/docker/.gitignore ---------------------------------------------------------------------- diff --git a/ambari-logsearch/docker/.gitignore b/ambari-logsearch/docker/.gitignore index 0d6af58..99455ed 100644 --- a/ambari-logsearch/docker/.gitignore +++ b/ambari-logsearch/docker/.gitignore @@ -1 +1 @@ -Profile \ No newline at end of file +Profile http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/docker/Dockerfile ---------------------------------------------------------------------- diff --git a/ambari-logsearch/docker/Dockerfile b/ambari-logsearch/docker/Dockerfile index a09f235..dfa1462 100644 --- a/ambari-logsearch/docker/Dockerfile +++ b/ambari-logsearch/docker/Dockerfile @@ -62,12 +62,12 @@ ADD test-logs /root/test-logs RUN chmod -R 777 /root/test-config RUN chmod +x /root/start.sh -ENV SOLR_CONFIG_LOCATION /root/test-config/solr -ENV LOGSEARCH_CONFIG_LOCATION /root/test-config/logsearch -ENV LOGFEEDER_CONFIG_LOCATION /root/test-config/logfeeder -ENV SOLR_INCLUDE /root/test-config/solr/solr-env.sh -ENV LOGSEARCH_INCLUDE /root/test-config/logsearch/logsearch-env.sh -ENV LOGFEEDER_INCLUDE /root/test-config/logfeeder/logfeeder-env.sh +ENV SOLR_CONFIG_LOCATION /root/config/solr +ENV LOGSEARCH_CONFIG_LOCATION /root/config/logsearch +ENV LOGFEEDER_CONFIG_LOCATION /root/config/logfeeder +ENV SOLR_INCLUDE /root/config/solr/solr-env.sh +ENV LOGSEARCH_INCLUDE /root/config/logsearch/logsearch-env.sh +ENV LOGFEEDER_INCLUDE /root/config/logfeeder/logfeeder-env.sh RUN mkdir -p /var/run/ambari-logsearch-solr /var/log/ambari-logsearch-solr /var/run/ambari-logsearch-solr-client \ /var/log/ambari-logsearch-solr-client /root/logsearch_solr_index/data \ @@ -78,4 +78,4 @@ RUN cp /root/test-config/solr/solr.xml /root/logsearch_solr_index/data RUN cp /root/test-config/solr/zoo.cfg /root/logsearch_solr_index/data WORKDIR /root -CMD /root/start.sh \ No newline at end of file +CMD /root/start.sh http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/docker/bin/start.sh ---------------------------------------------------------------------- diff --git a/ambari-logsearch/docker/bin/start.sh b/ambari-logsearch/docker/bin/start.sh index a09e4b2..81c9e66 100644 --- a/ambari-logsearch/docker/bin/start.sh +++ b/ambari-logsearch/docker/bin/start.sh @@ -28,27 +28,70 @@ function build_all() { cd $AMBARI_PATH/ambari-logsearch && mvn clean package -DskipTests && mvn -pl ambari-logsearch-logfeeder clean package -DskipTests } +function create_config() { + mkdir /root/config + + mkdir /root/config/solr + cp /root/test-config/solr/log4j.properties /root/config/solr/ + cp /root/test-config/solr/zoo.cfg /root/config/solr/ + cp /root/test-config/solr/solr.xml /root/config/solr/ + if [ $LOGSEARCH_SOLR_SSL_ENABLED == 'true' ] + then + cp /root/test-config/solr/solr-env-ssl.sh /root/config/solr/solr-env.sh + else + cp /root/test-config/solr/solr-env.sh /root/config/solr/solr-env.sh + fi + + mkdir /root/config/logfeeder + cp -r /root/test-config/logfeeder/* /root/config/logfeeder/ + + mkdir /root/config/logsearch + cp /root/test-config/logsearch/log4j.xml /root/config/logsearch/ + cp /root/test-config/logsearch/logsearch-env.sh /root/config/logsearch/ + if [ $LOGSEARCH_HTTPS_ENABLED == 'true' ] + then + cp /root/test-config/logsearch/logsearch-https.properties /root/config/logsearch/logsearch.properties + else + cp /root/test-config/logsearch/logsearch.properties /root/config/logsearch/logsearch.properties + fi + + chmod -R 777 /root/config +} + +function generate_keys() { + IP=`hostname --ip-address` + echo "generating stores for IP: $IP" + mkdir /root/config/ssl + keytool -genkeypair -alias logsearch -keyalg RSA -keysize 2048 -keypass bigdata -storepass bigdata -validity 9999 -keystore /root/config/ssl/logsearch.keyStore.jks -ext SAN=DNS:localhost,IP:127.0.0.1,IP:$IP -dname "CN=Common Name, OU=Organizational Unit, O=Organization, L=Location, ST=State, C=Country" -rfc + cp /root/config/ssl/logsearch.keyStore.jks /root/config/ssl/logsearch.trustStore.jks +} + function start_solr() { echo "Starting Solr..." /root/solr-$SOLR_VERSION/bin/solr start -cloud -s /root/logsearch_solr_index/data -verbose touch /var/log/ambari-logsearch-solr/solr.log + + if [ $LOGSEARCH_SOLR_SSL_ENABLED == 'true' ] + then + echo "Setting urlScheme as https and restarting solr..." + $ZKCLI -zkhost localhost:9983 -cmd clusterprop -name urlScheme -val https + /root/solr-$SOLR_VERSION/bin/solr stop + /root/solr-$SOLR_VERSION/bin/solr start -cloud -s /root/logsearch_solr_index/data -verbose + fi } function start_logsearch() { echo "Upload configuration sets ..." + $ZKCLI -zkhost localhost:9983 -cmd upconfig -confdir $LOGSEARCH_SERVER_PATH/solr_configsets/audit_logs/conf -confname audit_logs $ZKCLI -zkhost localhost:9983 -cmd upconfig -confdir $LOGSEARCH_SERVER_PATH/solr_configsets/hadoop_logs/conf -confname hadoop_logs $ZKCLI -zkhost localhost:9983 -cmd upconfig -confdir $LOGSEARCH_SERVER_PATH/solr_configsets/history/conf -confname history - - cp $LOGSEARCH_CONFIG_LOCATION/logsearch.properties /root/ambari/ambari-logsearch/ambari-logsearch-portal/target/package/classes/logsearch.properties - cp $LOGSEARCH_CONFIG_LOCATION/log4j.xml /root/ambari/ambari-logsearch/ambari-logsearch-portal/target/package/classes/logsearch.properties + $LOGSEARCH_SERVER_PATH/run.sh touch /var/log/ambari-logsearch-portal/logsearch-app.log } function start_logfeeder() { - cp $LOGFEEDER_CONFIG_LOCATION/logfeeder.properties /root/ambari/ambari-logsearch/ambari-logsearch-logfeeder/target/package/classes/logfeeder.properties - cp $LOGFEEDER_CONFIG_LOCATION/log4j.xml /root/ambari/ambari-logsearch/ambari-logsearch-logfeeder/target/package/classes/log4j.xml $LOGFEEDER_PATH/run.sh touch /var/log/ambari-logsearch-logfeeder/logsearch-logfeeder.log } @@ -68,10 +111,10 @@ function log() { esac } +create_config +generate_keys start_solr start_logsearch start_logfeeder log - - http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/docker/logsearch-docker.sh ---------------------------------------------------------------------- diff --git a/ambari-logsearch/docker/logsearch-docker.sh b/ambari-logsearch/docker/logsearch-docker.sh index 022b1ba..76994ee 100755 --- a/ambari-logsearch/docker/logsearch-docker.sh +++ b/ambari-logsearch/docker/logsearch-docker.sh @@ -57,8 +57,10 @@ function setup_profile() { AMBARI_LOCATION=$HOME/prj/ambari MAVEN_REPOSITORY_LOCATION=$HOME/.m2 LOGSEARCH_EXPOSED_PORTS="-p 8886:8886 -p 61888:61888 -p 5005:5005 -p 5006:5006" -LOGSEARCH_ENV_OPTS="-e LOGFEEDER_DEBUG_SUSPEND=n -e LOGSEARCH_DEBUG_SUSPEND=n -e COMPONENT_LOG=logsearch" -LOGSEARCH_VOLUME_OPTS="-v \$AMBARI_LOCATION/ambari-logsearch/docker/test-logs:/root/test-logs -v \$AMBARI_LOCATION/ambari-logsearch/docker/test-config:/root/test-config " +LOGSEARCH_ENV_OPTS="-e LOGFEEDER_DEBUG_SUSPEND=n -e LOGSEARCH_DEBUG_SUSPEND=n -e COMPONENT_LOG=logsearch -e LOGSEARCH_HTTPS_ENABLED=false -e LOGSEARCH_SOLR_SSL_ENABLED=false" + +LOGSEARCH_VOLUME_OPTS="-v $AMBARI_LOCATION/ambari-logsearch/docker/test-logs:/root/test-logs -v $AMBARI_LOCATION/ambari-logsearch/docker/test-config:/root/test-config" + LOGSEARCH_EXTRA_OPTS="" EOF echo "Profile has been created. Check it out before starting Log Search. ($sdir/Profile)" http://git-wip-us.apache.org/repos/asf/ambari/blob/fb70f1b9/ambari-logsearch/docker/test-config/logfeeder/logfeeder-env.sh ---------------------------------------------------------------------- diff --git a/ambari-logsearch/docker/test-config/logfeeder/logfeeder-env.sh b/ambari-logsearch/docker/test-config/logfeeder/logfeeder-env.sh index e69b1db..5beb093 100644 --- a/ambari-logsearch/docker/test-config/logfeeder/logfeeder-env.sh +++ b/ambari-logsearch/docker/test-config/logfeeder/logfeeder-env.sh @@ -18,7 +18,7 @@ set -e export LOGFEEDER_PATH=/root/ambari/ambari-logsearch/ambari-logsearch-logfeeder/target/package -export LOGFEEDER_CONF_DIR=/root/test-config/logfeeder +export LOGFEEDER_CONF_DIR=/root/config/logfeeder #Logfile e.g. /var/log/logfeeder.log export LOGFILE=/var/log/ambari-logsearch-logfeeder/logfeeder.out @@ -32,4 +32,13 @@ LOGFEEDER_JAVA_MEM=${LOGFEEDER_JAVA_MEM:-"-Xmx512m"} export LOGFEEDER_DEBUG=true -export LOGFEEDER_DEBUG_PORT=5006 \ No newline at end of file +export LOGFEEDER_DEBUG_PORT=5006 + +export LOGFEEDER_SSL="true" +export LOGFEEDER_KEYSTORE_LOCATION=/root/config/ssl/logsearch.keyStore.jks +export LOGFEEDER_KEYSTORE_PASSWORD=bigdata +export LOGFEEDER_KEYSTORE_TYPE=jks +export LOGFEEDER_TRUSTSTORE_LOCATION=/root/config/ssl/logsearch.trustStore.jks +export LOGFEEDER_TRUSTSTORE_PASSWORD=bigdata +export LOGFEEDER_TRUSTSTORE_TYPE=jks +