http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthBuilder.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthBuilder.java b/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthBuilder.java new file mode 100644 index 0000000..8d41a90 --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthBuilder.java @@ -0,0 +1,99 @@ +/* + * 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.eagle.server.security; + +import com.google.common.cache.CacheBuilderSpec; +import com.sun.jersey.api.core.HttpContext; +import com.sun.jersey.api.model.Parameter; +import com.sun.jersey.core.spi.component.ComponentContext; +import com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable; +import com.sun.jersey.spi.inject.Injectable; +import io.dropwizard.auth.Auth; +import io.dropwizard.auth.Authenticator; +import io.dropwizard.auth.CachingAuthenticator; +import io.dropwizard.auth.basic.BasicAuthProvider; +import io.dropwizard.auth.basic.BasicCredentials; +import io.dropwizard.setup.Environment; +import org.apache.eagle.common.security.User; +import org.apache.eagle.server.security.authenticator.LdapBasicAuthenticator; +import org.apache.eagle.server.security.authenticator.SimpleBasicAuthenticator; +import org.apache.eagle.server.security.config.AuthenticationConfig; + +import java.util.Arrays; + +public class BasicAuthBuilder { + private static final String SIMPLE_MODE_REALM = "SIMPLE_BASIC_AUTHENTICATION"; + private static final String LDAP_MODE_REALM = "LDAP_BASIC_AUTHENTICATION"; + private final Authenticator<BasicCredentials, User> authenticator; + private final BasicAuthProvider basicAuthProvider; + private AuthenticationConfig authConfig; + private Environment environment; + + public BasicAuthBuilder(AuthenticationConfig authConfig, Environment environment) { + this.authConfig = authConfig; + this.environment = environment; + boolean needsCaching = authConfig.needsCaching(); + Authenticator<BasicCredentials, User> authenticator; + String realm; + if (authConfig.isEnabled()) { + switch (authConfig.getMode()) { + case "simple": + authenticator = new SimpleBasicAuthenticator(authConfig.getSimple()); + realm = SIMPLE_MODE_REALM; + break; + case "ldap": + authenticator = new LdapBasicAuthenticator(authConfig.getLdap()); + realm = LDAP_MODE_REALM; + break; + default: + throw new IllegalArgumentException("Invalid auth mode " + authConfig.getMode()); + } + if (needsCaching) { + authenticator = cache(authenticator); + } + this.authenticator = authenticator; + this.basicAuthProvider = new BasicAuthProvider<>(this.authenticator, realm); + } else { + this.authenticator = null; + this.basicAuthProvider = new BasicAuthProvider<User>(null, "") { + public Injectable<User> getInjectable(ComponentContext ic, Auth a, Parameter c) { + return new AbstractHttpContextInjectable<User>() { + public User getValue(HttpContext c) { + User user = new User(); + user.setName("anonymous"); + user.setFirstName("Anonymous User (auth: false)"); + user.setRoles(Arrays.asList(User.Role.ALL_ROLES)); + return user; + } + }; + } + }; + } + } + + public BasicAuthProvider getBasicAuthProvider() { + return this.basicAuthProvider; + } + + public Authenticator<BasicCredentials, User> getBasicAuthenticator() { + return this.authenticator; + } + + private Authenticator<BasicCredentials, User> cache(Authenticator<BasicCredentials, User> authenticator) { + return new CachingAuthenticator<>(environment.metrics(), authenticator, CacheBuilderSpec.parse(authConfig.getCachePolicy())); + } +}
http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthRequestFilter.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthRequestFilter.java b/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthRequestFilter.java new file mode 100644 index 0000000..1542505 --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthRequestFilter.java @@ -0,0 +1,161 @@ +package org.apache.eagle.server.security; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.sun.jersey.api.model.AbstractMethod; +import com.sun.jersey.core.util.Base64; +import com.sun.jersey.core.util.Priority; +import com.sun.jersey.spi.container.ContainerRequest; +import com.sun.jersey.spi.container.ContainerRequestFilter; +import io.dropwizard.auth.Auth; +import io.dropwizard.auth.AuthenticationException; +import io.dropwizard.auth.Authenticator; +import io.dropwizard.auth.basic.BasicCredentials; +import org.apache.eagle.common.rest.RESTResponse; +import org.apache.eagle.common.security.DenyAll; +import org.apache.eagle.common.security.PermitAll; +import org.apache.eagle.common.security.RolesAllowed; +import org.apache.eagle.common.security.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.Priorities; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; +import javax.ws.rs.ext.Provider; +import java.lang.reflect.Parameter; +import java.security.Principal; +import java.util.Arrays; +import java.util.List; +import java.util.StringTokenizer; + +@Provider +@Priority(Priorities.AUTHORIZATION) +public class BasicAuthRequestFilter implements ContainerRequestFilter { + private final Authenticator<BasicCredentials, User> authenticator; + private final AbstractMethod method; + private static final Logger LOG = LoggerFactory.getLogger(BasicAuthRequestFilter.class); + private boolean isSecurityDefined = false; + private boolean isAuthRequired = false; + private boolean hasPermitAllAnnotation = false; + private boolean hasDenyAllAnnotation = false; + private boolean hasRolesAllowedAnnotation = false; + + public BasicAuthRequestFilter(Authenticator<BasicCredentials, User> authenticator, AbstractMethod method) { + this.authenticator = authenticator; + this.method = method; + this.hasPermitAllAnnotation = method.isAnnotationPresent(PermitAll.class); + this.hasDenyAllAnnotation = method.isAnnotationPresent(DenyAll.class); + this.hasRolesAllowedAnnotation = method.isAnnotationPresent(RolesAllowed.class); + this.isSecurityDefined = this.hasPermitAllAnnotation || this.hasDenyAllAnnotation || this.hasRolesAllowedAnnotation; + for (Parameter parameter : method.getMethod().getParameters()) { + if (isSecurityDefined && isAuthRequired) { + break; + } + Auth[] authAnnotations = parameter.getAnnotationsByType(Auth.class); + this.isSecurityDefined = this.isSecurityDefined || authAnnotations.length > 0; + for (Auth auth : authAnnotations) { + this.isAuthRequired = this.isAuthRequired || auth.required(); + } + } + Preconditions.checkArgument(!(this.hasDenyAllAnnotation && this.hasPermitAllAnnotation), "Conflict @DenyAll and @PermitAll on method " + this.method.toString()); + } + + + private static final String AUTHORIZATION_PROPERTY = "Authorization"; + private static final String AUTHENTICATION_SCHEME = "Basic"; + private static final Response UNAUTHORIZED_ACCESS_DENIED = RESTResponse.builder() + .message("Unauthorized access denied") + .status(false, Response.Status.UNAUTHORIZED) + .build(); + + private static final Response ALL_ACCESS_DENIED = RESTResponse.builder() + .message("Access denied") + .status(false, Response.Status.FORBIDDEN) + .build(); + + @Override + public ContainerRequest filter(ContainerRequest containerRequest) { + if (!isSecurityDefined) { + return containerRequest; + } + //Access denied for all + + if (hasDenyAllAnnotation) { + throw new WebApplicationException(ALL_ACCESS_DENIED); + } + + //Get request headers + final MultivaluedMap<String, String> headers = containerRequest.getRequestHeaders(); + + //Fetch authorization header + final List<String> authorization = headers.get(AUTHORIZATION_PROPERTY); + + //If no authorization information present; block access + if ((authorization == null || authorization.isEmpty()) && isAuthRequired) { + throw new WebApplicationException(UNAUTHORIZED_ACCESS_DENIED); + } + + if (authorization != null) { + //Get encoded username and password + final String encodedUserPassword = authorization.get(0).replaceFirst(AUTHENTICATION_SCHEME + " ", ""); + + //Decode username and password + String usernameAndPassword = new String(Base64.decode(encodedUserPassword.getBytes())); + + //Split username and password tokens + final StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":"); + final String username = tokenizer.nextToken(); + final String password = tokenizer.nextToken(); + + try { + Optional<User> userOptional = this.authenticator.authenticate(new BasicCredentials(username, password)); + if (userOptional.isPresent()) { + User user = userOptional.get(); + containerRequest.setSecurityContext(new SecurityContext() { + @Override + public Principal getUserPrincipal() { + return user; + } + + @Override + public boolean isUserInRole(String role) { + return user.isInRole(User.Role.locateCaseInsensitive(role)); + } + + @Override + public boolean isSecure() { + return "https".equals(containerRequest.getRequestUri().getScheme()); + } + + @Override + public String getAuthenticationScheme() { + return "Basic Auth"; + } + }); + + //Verify user access + if (hasRolesAllowedAnnotation && !hasPermitAllAnnotation) { + RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class); + if (!user.isInRole(rolesAnnotation.value())) { + throw new WebApplicationException( + RESTResponse.builder() + .status(false, Response.Status.FORBIDDEN) + .message("Access forbidden, required roles: " + Arrays.toString(rolesAnnotation.value())) + .build()); + } + } + } else { + throw new WebApplicationException(UNAUTHORIZED_ACCESS_DENIED); + } + } catch (AuthenticationException e) { + LOG.error("Server authentication error: " + e.getMessage(), e); + throw new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("Server authentication error: " + e.getMessage()).build()); + } + } + return containerRequest; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthResourceFilterFactory.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthResourceFilterFactory.java b/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthResourceFilterFactory.java new file mode 100644 index 0000000..e6b8522 --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/BasicAuthResourceFilterFactory.java @@ -0,0 +1,53 @@ +/* + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.eagle.server.security; + + +import com.sun.jersey.api.model.AbstractMethod; +import com.sun.jersey.spi.container.ContainerRequestFilter; +import com.sun.jersey.spi.container.ContainerResponseFilter; +import com.sun.jersey.spi.container.ResourceFilter; +import com.sun.jersey.spi.container.ResourceFilterFactory; +import io.dropwizard.auth.Authenticator; +import io.dropwizard.auth.basic.BasicCredentials; +import org.apache.eagle.common.security.User; + +import java.util.Arrays; +import java.util.List; + +public class BasicAuthResourceFilterFactory implements ResourceFilterFactory { + private final Authenticator<BasicCredentials, User> authenticator; + + public BasicAuthResourceFilterFactory(Authenticator<BasicCredentials, User> authenticator) { + this.authenticator = authenticator; + } + + @Override + public List<ResourceFilter> create(AbstractMethod abstractMethod) { + return Arrays.asList(new ResourceFilter() { + @Override + public ContainerRequestFilter getRequestFilter() { + return new BasicAuthRequestFilter(authenticator, abstractMethod); + } + + @Override + public ContainerResponseFilter getResponseFilter() { + return null; + } + }); + } +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/authenticator/LdapBasicAuthenticator.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/authenticator/LdapBasicAuthenticator.java b/eagle-server/src/main/java/org/apache/eagle/server/security/authenticator/LdapBasicAuthenticator.java new file mode 100644 index 0000000..bc50c82 --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/authenticator/LdapBasicAuthenticator.java @@ -0,0 +1,106 @@ +/* + * 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.eagle.server.security.authenticator; + +import com.google.common.base.Optional; +import io.dropwizard.auth.AuthenticationException; +import io.dropwizard.auth.Authenticator; +import io.dropwizard.auth.basic.BasicCredentials; +import org.apache.eagle.common.security.User; +import org.apache.eagle.server.security.config.LdapConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.naming.Context; +import javax.naming.directory.InitialDirContext; +import java.io.File; +import java.util.Hashtable; + +public class LdapBasicAuthenticator implements Authenticator<BasicCredentials, User> { + private static final Logger LOGGER = LoggerFactory.getLogger(LdapBasicAuthenticator.class); + private static final String LDAP_LDAP_CTX_FACTORY_NAME = "com.sun.jndi.ldap.LdapCtxFactory"; + private static final String LDAP_CONNECT_TIMEOUT_KEY = "com.sun.jndi.ldap.connect.timeout"; + private static final String LDAP_READ_TIMEOUT_KEY = "com.sun.jndi.ldap.read.timeout"; + private static final String SYS_PROP_SSL_KEY_STORE = "javax.net.ssl.keyStore"; + private static final String SYS_PROP_SSL_TRUST_STORE = "javax.net.ssl.trustStore"; + private static final String LDAPS_URL_PREFIX = "ldaps://"; + private static final String SSL_PROTOCOL_VALUE = "ssl"; + private LdapConfig settings = null; + + public LdapBasicAuthenticator(LdapConfig settings) { + this.settings = settings; + } + + public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException { + String sanitizedUsername = sanitizeUsername(credentials.getUsername()); + try { + new InitialDirContext(getContextEnvironment(sanitizedUsername, credentials.getPassword())); + return Optional.of(new User(sanitizedUsername)); + } catch (javax.naming.AuthenticationException ae) { + LOGGER.warn(String.format("Authentication failed for user[%s]: wrong username or password", sanitizedUsername)); + return Optional.absent(); + } catch (Exception e) { + throw new AuthenticationException(String.format("Error occurs while trying to authenticate for user[%s]: %s", sanitizedUsername, e.getMessage()), e); + } + } + + Hashtable<String, String> getContextEnvironment(String sanitizedUsername, String password) { + String providerUrl = settings.getProviderUrl(); + if (providerUrl == null) { + throw new IllegalArgumentException("providerUrl of the ldap service shouldn't be null"); + } + + Hashtable<String, String> env = new Hashtable<>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, LDAP_LDAP_CTX_FACTORY_NAME); + env.put(Context.PROVIDER_URL, providerUrl); + env.put(LDAP_CONNECT_TIMEOUT_KEY, String.valueOf(settings.getConnectingTimeout().toMilliseconds())); + env.put(LDAP_READ_TIMEOUT_KEY, String.valueOf(settings.getReadingTimeout().toMilliseconds())); + + String strategy = settings.getStrategy(); + if (!"".equals(strategy)) { + env.put(Context.SECURITY_AUTHENTICATION, strategy); + } + + if (providerUrl.toLowerCase().startsWith(LDAPS_URL_PREFIX)) { // using ldap over ssl to authenticate + env.put(Context.SECURITY_PROTOCOL, SSL_PROTOCOL_VALUE); + + String certificateAbsolutePath = settings.getCertificateAbsolutePath(); + if (certificateAbsolutePath == null || "".equals(certificateAbsolutePath)) { + throw new RuntimeException("The attribute 'certificateAbsolutePath' must be set when using ldap over ssl to authenticate."); + } + if (!new File(certificateAbsolutePath).exists()) { + throw new RuntimeException(String.format("The file specified not existing: %s", certificateAbsolutePath)); + } + + System.setProperty(SYS_PROP_SSL_KEY_STORE, certificateAbsolutePath); + System.setProperty(SYS_PROP_SSL_TRUST_STORE, certificateAbsolutePath); + } + + env.put(Context.SECURITY_PRINCIPAL, comprisePrincipal(sanitizedUsername)); + env.put(Context.SECURITY_CREDENTIALS, password); + return env; + } + + String comprisePrincipal(String sanitizedUsername) { + return settings.getPrincipalTemplate().replaceAll("\\$\\{USERNAME\\}", sanitizedUsername); + } + + String sanitizeUsername(String username) { + return username.replaceAll("[^a-zA-Z0-9_.]", ""); + } + +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/authenticator/SimpleBasicAuthenticator.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/authenticator/SimpleBasicAuthenticator.java b/eagle-server/src/main/java/org/apache/eagle/server/security/authenticator/SimpleBasicAuthenticator.java new file mode 100644 index 0000000..63dfd3b --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/authenticator/SimpleBasicAuthenticator.java @@ -0,0 +1,59 @@ +/* + * 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.eagle.server.security.authenticator; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import io.dropwizard.auth.AuthenticationException; +import io.dropwizard.auth.Authenticator; +import io.dropwizard.auth.basic.BasicCredentials; +import org.apache.eagle.common.security.User; +import org.apache.eagle.server.security.config.SimpleConfig; +import org.apache.eagle.server.security.config.UserAccount; +import org.apache.eagle.server.security.encrypt.EncryptorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +public class SimpleBasicAuthenticator implements Authenticator<BasicCredentials, User> { + private static final Logger LOGGER = LoggerFactory.getLogger(SimpleBasicAuthenticator.class); + private final Map<String, UserAccount> userAccountRepository; + + public SimpleBasicAuthenticator(SimpleConfig config) { + userAccountRepository = new HashMap<>(); + for (UserAccount userAccount : config.getAccounts()) { + Preconditions.checkNotNull(userAccount.getName(), " Username is null " + userAccount); + Preconditions.checkArgument(!userAccountRepository.containsKey(userAccount.getName()), "Duplicated user name: " + userAccount.getName()); + if (userAccount.getRoles() == null) { + LOGGER.warn("UserPrincipal {} has no roles, set as {} by default", userAccount.getName(), User.Role.USER); + userAccount.setRoles(User.Role.USER.toString()); + } + userAccountRepository.put(userAccount.getName(), userAccount); + } + } + + public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException { + if (userAccountRepository.containsKey(credentials.getUsername()) + && EncryptorFactory.getPasswordEncryptor().checkPassword(credentials.getPassword(), userAccountRepository.get(credentials.getUsername()).getEncryptedPassword())) { + UserAccount userAccount = userAccountRepository.get(credentials.getUsername()); + return Optional.of(new User(userAccount)); + } else { + return Optional.absent(); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/config/AuthenticationConfig.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/config/AuthenticationConfig.java b/eagle-server/src/main/java/org/apache/eagle/server/security/config/AuthenticationConfig.java new file mode 100644 index 0000000..dbbb13b --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/config/AuthenticationConfig.java @@ -0,0 +1,95 @@ +/* + * 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.eagle.server.security.config; + +import io.dropwizard.Configuration; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AuthenticationConfig extends Configuration { + private boolean enabled = false; + private String mode = null; + private boolean caching = false; + private String cachePolicy = null; + private SimpleConfig simple = new SimpleConfig(); + private LdapConfig ldap = new LdapConfig(); + + @JsonProperty + public boolean isEnabled() { + return enabled; + } + + @JsonProperty + public AuthenticationConfig setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + @JsonProperty + public String getMode() { + return mode; + } + + @JsonProperty + public AuthenticationConfig setMode(String mode) { + this.mode = mode; + return this; + } + + @JsonProperty + public boolean needsCaching() { + return caching; + } + + @JsonProperty + public AuthenticationConfig setCaching(boolean caching) { + this.caching = caching; + return this; + } + + @JsonProperty + public String getCachePolicy() { + return cachePolicy; + } + + @JsonProperty + public AuthenticationConfig setCachePolicy(String cachePolicy) { + this.cachePolicy = cachePolicy; + return this; + } + + @JsonProperty("ldap") + public LdapConfig getLdap() { + return ldap; + } + + @JsonProperty("ldap") + public AuthenticationConfig setLdap(LdapConfig ldap) { + this.ldap = ldap; + return this; + } + + @JsonProperty("simple") + public SimpleConfig getSimple() { + return simple; + } + + @JsonProperty("simple") + public AuthenticationConfig setSimple(SimpleConfig simple) { + this.simple = simple; + return this; + } +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/config/LdapConfig.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/config/LdapConfig.java b/eagle-server/src/main/java/org/apache/eagle/server/security/config/LdapConfig.java new file mode 100644 index 0000000..c87553f --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/config/LdapConfig.java @@ -0,0 +1,96 @@ +/* + * 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.eagle.server.security.config; + +import io.dropwizard.util.Duration; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class LdapConfig { + + private String providerUrl = ""; + private String strategy = ""; + private String principalTemplate = ""; + private String certificateAbsolutePath = ""; + private Duration connectingTimeout = Duration.parse("500ms"); + private Duration readingTimeout = Duration.parse("500ms"); + + @JsonProperty + public String getProviderUrl() { + return providerUrl; + } + + @JsonProperty + public LdapConfig setProviderUrl(String providerUrl) { + this.providerUrl = providerUrl; + return this; + } + + @JsonProperty + public String getPrincipalTemplate() { + return principalTemplate; + } + + @JsonProperty + public LdapConfig setPrincipalTemplate(String principalTemplate) { + this.principalTemplate = principalTemplate; + return this; + } + + @JsonProperty + public String getStrategy() { + return strategy; + } + + @JsonProperty + public LdapConfig setStrategy(String strategy) { + this.strategy = strategy; + return this; + } + + @JsonProperty + public Duration getConnectingTimeout() { + return connectingTimeout; + } + + @JsonProperty + public LdapConfig setConnectingTimeout(Duration connectingTimeout) { + this.connectingTimeout = connectingTimeout; + return this; + } + + @JsonProperty + public Duration getReadingTimeout() { + return readingTimeout; + } + + @JsonProperty + public LdapConfig setReadingTimeout(Duration readingTimeout) { + this.readingTimeout = readingTimeout; + return this; + } + + @JsonProperty + public String getCertificateAbsolutePath() { + return certificateAbsolutePath; + } + + @JsonProperty + public LdapConfig setCertificateAbsolutePath(String certificateAbsolutePath) { + this.certificateAbsolutePath = certificateAbsolutePath; + return this; + } +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/config/SimpleConfig.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/config/SimpleConfig.java b/eagle-server/src/main/java/org/apache/eagle/server/security/config/SimpleConfig.java new file mode 100644 index 0000000..65ae10f --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/config/SimpleConfig.java @@ -0,0 +1,34 @@ +/* + * 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.eagle.server.security.config; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public class SimpleConfig { + private List<UserAccount> accounts; + + @JsonProperty("accounts") + public List<UserAccount> getAccounts() { + return accounts; + } + + public void setAccounts(List<UserAccount> accounts) { + this.accounts = accounts; + } +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/config/UserAccount.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/config/UserAccount.java b/eagle-server/src/main/java/org/apache/eagle/server/security/config/UserAccount.java new file mode 100644 index 0000000..882e797 --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/config/UserAccount.java @@ -0,0 +1,55 @@ +/* + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.eagle.server.security.config; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Preconditions; +import org.apache.eagle.common.security.User; + +import java.util.*; + +public class UserAccount extends User { + + @JsonProperty("password") + public String getEncryptedPassword() { + return encryptedPassword; + } + + private String encryptedPassword; + + public UserAccount() { + + } + + public UserAccount(String username, String encryptedPassword) { + this.setName(username); + this.encryptedPassword = encryptedPassword; + } + + public void setRoles(String roles) { + if (roles != null) { + String[] roleStrArray = roles.split(","); + Set<User.Role> rolesSet = new HashSet<>(); + for (String roleStr:roleStrArray) { + User.Role role = User.Role.locateCaseInsensitive(roleStr.trim()); + Preconditions.checkNotNull(role, "Invalid role " + roleStr); + rolesSet.add(role); + } + super.setRoles(rolesSet); + } + } +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/EncryptorFactory.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/EncryptorFactory.java b/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/EncryptorFactory.java new file mode 100644 index 0000000..ff90213 --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/EncryptorFactory.java @@ -0,0 +1,23 @@ +/* + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.eagle.server.security.encrypt; + +public class EncryptorFactory { + public static PasswordEncryptor getPasswordEncryptor() { + return new PasswordEncryptorImpl(); + } +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/PasswordEncryptor.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/PasswordEncryptor.java b/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/PasswordEncryptor.java new file mode 100644 index 0000000..acf679e --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/PasswordEncryptor.java @@ -0,0 +1,23 @@ +/* + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.eagle.server.security.encrypt; + +public interface PasswordEncryptor { + String encryptPassword(String password); + + boolean checkPassword(String password, String encryptedPassword); +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/PasswordEncryptorImpl.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/PasswordEncryptorImpl.java b/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/PasswordEncryptorImpl.java new file mode 100644 index 0000000..2c93c3c --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/security/encrypt/PasswordEncryptorImpl.java @@ -0,0 +1,37 @@ +/* + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.eagle.server.security.encrypt; + +import org.jasypt.util.password.StrongPasswordEncryptor; + +class PasswordEncryptorImpl implements PasswordEncryptor { + private final StrongPasswordEncryptor encryptor; + + PasswordEncryptorImpl() { + this.encryptor = new StrongPasswordEncryptor(); + } + + @Override + public String encryptPassword(String password) { + return this.encryptor.encryptPassword(password); + } + + @Override + public boolean checkPassword(String password, String encryptedPassword) { + return this.encryptor.checkPassword(password, encryptedPassword); + } +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/tool/EncryptTool.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/tool/EncryptTool.java b/eagle-server/src/main/java/org/apache/eagle/server/tool/EncryptTool.java new file mode 100644 index 0000000..f77d90d --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/tool/EncryptTool.java @@ -0,0 +1,42 @@ +/* + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.eagle.server.tool; + +import org.apache.eagle.server.ServerMain; +import org.apache.eagle.server.security.encrypt.EncryptorFactory; +import org.apache.eagle.server.security.encrypt.PasswordEncryptor; + +public class EncryptTool implements Tool { + + private static final String MISSING_TEXT = + "Error: require text to encrypt\n" + + "Usage: java " + ServerMain.class.getName() + " encrypt [text to encrypt]"; + + @Override + public void execute(String[] args) { + if (args.length < 2) { + System.err.println(MISSING_TEXT); + } else { + String textToEncrypt = args[1]; + PasswordEncryptor encryptor = EncryptorFactory.getPasswordEncryptor(); + String encryptedText = encryptor.encryptPassword(textToEncrypt); + System.out.println("Original: " + textToEncrypt); + System.out.println("Encrypted: " + encryptedText); + System.exit(0); + } + } +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/java/org/apache/eagle/server/tool/Tool.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/java/org/apache/eagle/server/tool/Tool.java b/eagle-server/src/main/java/org/apache/eagle/server/tool/Tool.java new file mode 100644 index 0000000..bb5632a --- /dev/null +++ b/eagle-server/src/main/java/org/apache/eagle/server/tool/Tool.java @@ -0,0 +1,21 @@ +/* + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.eagle.server.tool; + +public interface Tool { + public void execute(String[] args); +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/main/resources/configuration.yml ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/resources/configuration.yml b/eagle-server/src/main/resources/configuration.yml index eabb8a1..a208f57 100644 --- a/eagle-server/src/main/resources/configuration.yml +++ b/eagle-server/src/main/resources/configuration.yml @@ -1,77 +1,74 @@ -# 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. - -server: - applicationConnectors: - - type: http - port: 9090 - adminConnectors: - - type: http - port: 9091 - -# --------------------------------------------- -# Eagle Authentication Configuration -# --------------------------------------------- -auth: - # indicating if authentication is enabled, true for enabled, false for disabled - enabled: false - - # indicating authentication mode, "simple" or "ldap" - mode: simple - - # indicating whether to use cache: cache is usually used for authentications that may - # not handle high throughput (an RDBMS or LDAP server, for example) - caching: false - - # indicating the cache policy, containing maximumSize and expireAfterWrite, e.g. maximumSize=10000, expireAfterWrite=10m - cachePolicy: maximumSize=10000, expireAfterWrite=1m - - # indicating whether authorization is needed - authorization: false - - # indicating whether @Auth annotation on parameters is needed - annotated: true - - # for basic authentication, effective only when auth.mode=simple - simple: - # username for basic authentication, effective only when auth.mode=simple - username: admin - # password for basic authentication, effective only when auth.mode=simple - password: secret - - # for ldap authentication, effective only when auth.mode=ldap - ldap: - # url providing ldap service. By convention, the port for typical ldap service is 389, and ldap service over ssl - # uses port 636 with protocol "ldaps", which requires certificates pre-installed. - providerUrl: ldap://server.address.or.domain:port - - # template string containing ${USERNAME} placeholder. This is designed for some orgs who don't use plain usernames - # to authenticate, e.g. they may use its members' email address as the username: ${USERNAME}@some.org. When username - # is supposed to be recognized originally, just configure this parameter as ${USERNAME} - principalTemplate: ${USERNAME}@maybe.email.suffix - - # string of strategy used by ldap service. "simple" is usually supported in most circumstances, we can use it by - # default or leave it a blank string. - strategy: simple - - # the absolute path of ssl certificate file. This attribute is required conditional only when the auth -> mode is set - # as "ldap" and providerUrl starting with "ldaps://". - certificateAbsolutePath: /certificate/absolute/path - - # timeout expression for connecting to ldap service endpoint - connectingTimeout: 500ms - - # timeout expression for reading from ldap service - readingTimeout: 500ms +# 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. + +server: + applicationConnectors: + - type: http + port: 9090 + adminConnectors: + - type: http + port: 9091 + +# --------------------------------------------- +# Eagle Authentication Configuration +# --------------------------------------------- +auth: + # indicating if authentication is enabled, true for enabled, false for disabled + enabled: false + + # indicating authentication mode, "simple" or "ldap" + mode: simple + + # indicating whether to use cache: cache is usually used for authentications that may + # not handle high throughput (an RDBMS or LDAP server, for example) + caching: false + + # indicating the cache policy, containing maximumSize and expireAfterWrite, e.g. maximumSize=10000, expireAfterWrite=10m + cachePolicy: maximumSize=10000, expireAfterWrite=1m + + # for basic authentication, effective only when auth.mode=simple + simple: + accounts: + - name: admin + password: rWV/cdTCr01wTLBQ/rUilkExd2TJKrifXuCCTEwig1o08K8Mi0b1qQAgVXpPqflb + roles: ADMINISTRATOR + firstName: Admin + lastName: Admin + email: [email protected] + + # for ldap authentication, effective only when auth.mode=ldap + ldap: + # url providing ldap service. By convention, the port for typical ldap service is 389, and ldap service over ssl + # uses port 636 with protocol "ldaps", which requires certificates pre-installed. + providerUrl: ldap://server.address.or.domain:port + + # template string containing ${USERNAME} placeholder. This is designed for some orgs who don't use plain usernames + # to authenticate, e.g. they may use its members' email address as the name: ${USERNAME}@some.org. When name + # is supposed to be recognized originally, just configure this parameter as ${USERNAME} + principalTemplate: ${USERNAME}@maybe.email.suffix + + # string of strategy used by ldap service. "simple" is usually supported in most circumstances, we can use it by + # default or leave it a blank string. + strategy: simple + + # the absolute path of ssl certificate file. This attribute is required conditional only when the auth -> mode is set + # as "ldap" and providerUrl starting with "ldaps://". + certificateAbsolutePath: /certificate/absolute/path + + # timeout expression for connecting to ldap service endpoint + connectingTimeout: 500ms + + # timeout expression for reading from ldap service + readingTimeout: 500ms http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/test/java/org/apache/eagle/server/ServerApplicationTest.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/test/java/org/apache/eagle/server/ServerApplicationTest.java b/eagle-server/src/test/java/org/apache/eagle/server/ServerApplicationTest.java deleted file mode 100644 index 6b299e5..0000000 --- a/eagle-server/src/test/java/org/apache/eagle/server/ServerApplicationTest.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 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 - * <p/> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p/> - * 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.eagle.server; - -import org.junit.Test; - -public class ServerApplicationTest { - @Test - public void testServerMain() throws Exception { - ServerMain.main(new String[] {"server", "src/test/resources/configuration.yml"}); - } -} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/test/java/org/apache/eagle/server/ServerDebug.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/test/java/org/apache/eagle/server/ServerDebug.java b/eagle-server/src/test/java/org/apache/eagle/server/ServerDebug.java index f47f2bf..3225435 100644 --- a/eagle-server/src/test/java/org/apache/eagle/server/ServerDebug.java +++ b/eagle-server/src/test/java/org/apache/eagle/server/ServerDebug.java @@ -16,9 +16,11 @@ */ package org.apache.eagle.server; +import org.junit.Ignore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@Ignore public class ServerDebug { private static final Logger LOGGER = LoggerFactory.getLogger(ServerDebug.class); private static String serverConf = null; http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticatorTest.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticatorTest.java b/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticatorTest.java deleted file mode 100644 index 8700a75..0000000 --- a/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticatorTest.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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.eagle.server.authentication.authenticator; - -import io.dropwizard.util.Duration; -import org.apache.eagle.server.authentication.config.LdapSettings; -import org.junit.Assert; -import org.junit.Test; - -import javax.naming.Context; -import java.util.Hashtable; - -public class LdapBasicAuthenticatorTest { - - private static final String USERNAME_SUFFIX = "@some.emailbox.suffix"; - private static final String USERNAME_TEMPLATE = "${USERNAME}" + USERNAME_SUFFIX; - private static final String LDAP_SERVICE_PROVIDER_URL = "ldap://some.address:port"; - private static final String LDAP_SERVICE_PROVIDER_SSL_URL = "ldaps://some.address:port"; - private static final String STRATEGY_SIMPLE = "customized"; - private static final String CONNECTING_TIMEOUT_VALUE = "500ms"; - private static final String READING_TIMEOUT_VALUE = "800ms"; - private static final String LDAP_CTX_FACTORY_NAME = "com.sun.jndi.ldap.LdapCtxFactory"; - private static final String LDAP_CONNECT_TIMEOUT_KEY = "com.sun.jndi.ldap.connect.timeout"; - private static final String LDAP_READ_TIMEOUT_KEY = "com.sun.jndi.ldap.read.timeout"; - private static final String SYS_PROP_SSL_KEY_STORE = "javax.net.ssl.keyStore"; - private static final String SYS_PROP_SSL_TRUST_STORE = "javax.net.ssl.trustStore"; - private static final String EXISTING_MOCK_FILE_PATH = String.format("%s/pom.xml", System.getProperty("user.dir")); - private static final LdapBasicAuthenticator AUTHENTICATOR_FOR_UTIL_METHODS_WITHOUT_SSL = new LdapBasicAuthenticator( - getNonSSLPreSettings().setPrincipalTemplate(USERNAME_TEMPLATE) - .setStrategy(STRATEGY_SIMPLE) - .setConnectingTimeout(Duration.parse(CONNECTING_TIMEOUT_VALUE)) - .setReadingTimeout(Duration.parse(READING_TIMEOUT_VALUE)) - ); - private static final LdapBasicAuthenticator AUTHENTICATOR_FOR_UTIL_METHODS_WITH_SSL = new LdapBasicAuthenticator( - getSSLPreSettings().setPrincipalTemplate(USERNAME_TEMPLATE) - .setStrategy(STRATEGY_SIMPLE) - .setCertificateAbsolutePath(EXISTING_MOCK_FILE_PATH) - .setConnectingTimeout(Duration.parse(CONNECTING_TIMEOUT_VALUE)) - .setReadingTimeout(Duration.parse(READING_TIMEOUT_VALUE)) - ); - - @Test - public void testSanitizeUsername() { - String correctUsername = "userNAME_123.45Z"; - String sanitized = AUTHENTICATOR_FOR_UTIL_METHODS_WITHOUT_SSL.sanitizeUsername(correctUsername); - Assert.assertEquals(correctUsername, sanitized); - - String incorrectUsername = "userNAME-~!@#$%^&777*()_+-=`[]\\{}|;':\",./<>?ä½ "; - sanitized = AUTHENTICATOR_FOR_UTIL_METHODS_WITHOUT_SSL.sanitizeUsername(incorrectUsername); - System.out.println(sanitized); - Assert.assertEquals("userNAME777_.", sanitized); - } - - @Test - public void testComprisePrincipal() { - String username = "my.userNAME_123"; - String principal = AUTHENTICATOR_FOR_UTIL_METHODS_WITHOUT_SSL.comprisePrincipal(username); - Assert.assertEquals(username+USERNAME_SUFFIX, principal); - } - - @Test - public void testGetContextEnvironmentNormal() { - String username = "username"; - String secretPhrase = "secret-phrase"; - Hashtable<String, String> env = AUTHENTICATOR_FOR_UTIL_METHODS_WITHOUT_SSL.getContextEnvironment(username, secretPhrase); - - Assert.assertEquals("unexpected ldap context factory name", LDAP_CTX_FACTORY_NAME, env.get(Context.INITIAL_CONTEXT_FACTORY)); - Assert.assertEquals("unexpected ldap service provider url", LDAP_SERVICE_PROVIDER_URL, env.get(Context.PROVIDER_URL)); - Assert.assertEquals("unexpected connecting timeout value", String.valueOf(Duration.parse(CONNECTING_TIMEOUT_VALUE).toMilliseconds()), env.get(LDAP_CONNECT_TIMEOUT_KEY)); - Assert.assertEquals("unexpected reading timeout value", String.valueOf(Duration.parse(READING_TIMEOUT_VALUE).toMilliseconds()), env.get(LDAP_READ_TIMEOUT_KEY)); - Assert.assertEquals("unexpected username", username+USERNAME_SUFFIX, env.get(Context.SECURITY_PRINCIPAL)); - Assert.assertEquals("unexpected secret credentials", secretPhrase, env.get(Context.SECURITY_CREDENTIALS)); - Assert.assertEquals("unexpected strategy", STRATEGY_SIMPLE, env.get(Context.SECURITY_AUTHENTICATION)); - } - - @Test - public void testGetContextEnvironmentBlankStrategy() { - String username = "username"; - String secretPhrase = "secret-phrase"; - - // check strategy while it's configured as "" - LdapBasicAuthenticator blankStrategyAuthenticator = new LdapBasicAuthenticator(getNonSSLPreSettings().setStrategy("")); - String strategyMaybeBlank = blankStrategyAuthenticator.getContextEnvironment(username, secretPhrase).get(Context.SECURITY_AUTHENTICATION); - Assert.assertNull("unexpected strategy", strategyMaybeBlank); - } - - @Test - public void testGetContextEnvironmentNormalWithSSL() { - String username = "username"; - String secretPhrase = "secret-phrase"; - Hashtable<String, String> env = AUTHENTICATOR_FOR_UTIL_METHODS_WITH_SSL.getContextEnvironment(username, secretPhrase); - - Assert.assertEquals("unexpected ldap context factory name", LDAP_CTX_FACTORY_NAME, env.get(Context.INITIAL_CONTEXT_FACTORY)); - Assert.assertEquals("unexpected ldap service provider url", LDAP_SERVICE_PROVIDER_SSL_URL, env.get(Context.PROVIDER_URL)); - Assert.assertEquals("unexpected connecting timeout value", String.valueOf(Duration.parse(CONNECTING_TIMEOUT_VALUE).toMilliseconds()), env.get(LDAP_CONNECT_TIMEOUT_KEY)); - Assert.assertEquals("unexpected reading timeout value", String.valueOf(Duration.parse(READING_TIMEOUT_VALUE).toMilliseconds()), env.get(LDAP_READ_TIMEOUT_KEY)); - Assert.assertEquals("unexpected username", username+USERNAME_SUFFIX, env.get(Context.SECURITY_PRINCIPAL)); - Assert.assertEquals("unexpected secret credentials", secretPhrase, env.get(Context.SECURITY_CREDENTIALS)); - Assert.assertEquals("unexpected strategy", STRATEGY_SIMPLE, env.get(Context.SECURITY_AUTHENTICATION)); - Assert.assertEquals("unexpected key-store path", EXISTING_MOCK_FILE_PATH, System.getProperty(SYS_PROP_SSL_KEY_STORE)); - Assert.assertEquals("unexpected trust-store path", EXISTING_MOCK_FILE_PATH, System.getProperty(SYS_PROP_SSL_TRUST_STORE)); - } - - @Test - public void testGetContextEnvironmentMeaninglessCAPathSSL() { - String username = "username"; - String secretPhrase = "secret-phrase"; - - // check null certificateAbsolutePath - try { - LdapBasicAuthenticator blankStrategyAuthenticator = new LdapBasicAuthenticator(getSSLPreSettings().setCertificateAbsolutePath(null)); - blankStrategyAuthenticator.getContextEnvironment(username, secretPhrase).get(Context.SECURITY_AUTHENTICATION); - } - catch (Exception e) { - Assert.assertEquals("unexpected exception thrown", RuntimeException.class, e.getClass()); - Assert.assertEquals("unexpected exception message", "The attribute 'certificateAbsolutePath' must be set when using ldap over ssl to authenticate.", e.getMessage()); - } - - // check "" certificateAbsolutePath - try { - LdapBasicAuthenticator blankStrategyAuthenticator = new LdapBasicAuthenticator(getSSLPreSettings().setCertificateAbsolutePath("")); - blankStrategyAuthenticator.getContextEnvironment(username, secretPhrase).get(Context.SECURITY_AUTHENTICATION); - } - catch (Exception e) { - Assert.assertEquals("unexpected exception thrown", RuntimeException.class, e.getClass()); - Assert.assertEquals("unexpected exception message", "The attribute 'certificateAbsolutePath' must be set when using ldap over ssl to authenticate.", e.getMessage()); - } - } - - @Test - public void testGetContextEnvironmentUnexistingCA_SSL() { - String username = "username"; - String secretPhrase = "secret-phrase"; - String wrongCAPath = String.format("%s/this/cannot/be/existing", System.getProperty("user.dir")); - try { - // check with not existing path indicated by certificateAbsolutePath - LdapBasicAuthenticator blankStrategyAuthenticator = new LdapBasicAuthenticator(getSSLPreSettings().setCertificateAbsolutePath(wrongCAPath)); - blankStrategyAuthenticator.getContextEnvironment(username, secretPhrase).get(Context.SECURITY_AUTHENTICATION); - } - catch (Exception e) { - Assert.assertEquals("unexpected exception thrown", RuntimeException.class, e.getClass()); - Assert.assertEquals("unexpected exception message", String.format("The file specified not existing: %s", wrongCAPath), e.getMessage()); - } - } - - private static LdapSettings getNonSSLPreSettings() { - return new LdapSettings().setProviderUrl(LDAP_SERVICE_PROVIDER_URL); - } - - private static LdapSettings getSSLPreSettings() { - return new LdapSettings().setProviderUrl(LDAP_SERVICE_PROVIDER_SSL_URL); - } -} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticatorTest.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticatorTest.java b/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticatorTest.java deleted file mode 100644 index e896a7c..0000000 --- a/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticatorTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.eagle.server.authentication.authenticator; - -import com.google.common.base.Optional; -import io.dropwizard.auth.AuthenticationException; -import io.dropwizard.auth.basic.BasicCredentials; -import org.apache.eagle.common.authentication.User; -import org.apache.eagle.server.authentication.config.SimpleSettings; -import org.junit.Assert; -import org.junit.Test; - -public class SimpleBasicAuthenticatorTest { - - private static final String TEST_USERNAME = "normal-username"; - private static final String TEST_SECRET_PHRASE = "secret-phrase"; - private static final String TEST_UNEXISTING_USERNAME = "unexisting-username"; - private static final String TEST_WRONG_SECRET_PHRASE = "wrong-secret-phrase"; - private static SimpleBasicAuthenticator authenticator = new SimpleBasicAuthenticator(new SimpleSettings().setUsername(TEST_USERNAME).setPassword(TEST_SECRET_PHRASE)); - - @Test - public void testNormal() { - try { - BasicCredentials credentials = new BasicCredentials(TEST_USERNAME, TEST_SECRET_PHRASE); - Optional<User> result = authenticator.authenticate(credentials); - Assert.assertTrue("result isn't present when passed correct credentials", result.isPresent()); - User user = result.get(); - Assert.assertEquals("authenticated user is not expected", TEST_USERNAME, user.getName()); - } - catch (AuthenticationException e) { - Assert.fail("unexpected error occurs: "+e.getMessage()); - } - } - - @Test - public void testUnexistingUsername() { - try { - Optional<User> result = authenticator.authenticate(new BasicCredentials(TEST_UNEXISTING_USERNAME, TEST_SECRET_PHRASE)); - Assert.assertFalse("result is present when passed unexisting username", result.isPresent()); - } - catch (AuthenticationException e) { - Assert.fail("unexpected error occurs: "+e.getMessage()); - } - } - - @Test - public void testWrongPassword() { - try { - Optional<User> result = authenticator.authenticate(new BasicCredentials(TEST_USERNAME, TEST_WRONG_SECRET_PHRASE)); - Assert.assertFalse("result is present when passed wrong password", result.isPresent()); - } - catch (AuthenticationException e) { - Assert.fail("unexpected error occurs: "+e.getMessage()); - } - } -} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/test/java/org/apache/eagle/server/authentication/resource/TestBasicAuthenticationResource.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/test/java/org/apache/eagle/server/authentication/resource/TestBasicAuthenticationResource.java b/eagle-server/src/test/java/org/apache/eagle/server/authentication/resource/TestBasicAuthenticationResource.java deleted file mode 100644 index 0ea6666..0000000 --- a/eagle-server/src/test/java/org/apache/eagle/server/authentication/resource/TestBasicAuthenticationResource.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.eagle.server.authentication.resource; - -import io.dropwizard.auth.Auth; -import org.apache.eagle.common.authentication.User; -import org.apache.eagle.metadata.resource.RESTResponse; -import org.junit.Ignore; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -@Ignore -@Path("/test") -public class TestBasicAuthenticationResource { - @GET - @Path("/ba/simple") - @Produces(MediaType.APPLICATION_JSON) - public RESTResponse<User> getIt(@Auth User user) { - return RESTResponse.<User>builder().data(user).success(true).status(Response.Status.OK).get(); - } -} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/test/java/org/apache/eagle/server/security/authenticator/LdapBasicAuthenticatorTest.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/test/java/org/apache/eagle/server/security/authenticator/LdapBasicAuthenticatorTest.java b/eagle-server/src/test/java/org/apache/eagle/server/security/authenticator/LdapBasicAuthenticatorTest.java new file mode 100644 index 0000000..8389da8 --- /dev/null +++ b/eagle-server/src/test/java/org/apache/eagle/server/security/authenticator/LdapBasicAuthenticatorTest.java @@ -0,0 +1,168 @@ +/* + * 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.eagle.server.security.authenticator; + +import io.dropwizard.util.Duration; +import org.apache.eagle.server.security.config.LdapConfig; +import org.junit.Assert; +import org.junit.Test; + +import javax.naming.Context; +import java.util.Hashtable; + +public class LdapBasicAuthenticatorTest { + + private static final String USERNAME_SUFFIX = "@some.emailbox.suffix"; + private static final String USERNAME_TEMPLATE = "${USERNAME}" + USERNAME_SUFFIX; + private static final String LDAP_SERVICE_PROVIDER_URL = "ldap://some.address:port"; + private static final String LDAP_SERVICE_PROVIDER_SSL_URL = "ldaps://some.address:port"; + private static final String STRATEGY_SIMPLE = "customized"; + private static final String CONNECTING_TIMEOUT_VALUE = "500ms"; + private static final String READING_TIMEOUT_VALUE = "800ms"; + private static final String LDAP_CTX_FACTORY_NAME = "com.sun.jndi.ldap.LdapCtxFactory"; + private static final String LDAP_CONNECT_TIMEOUT_KEY = "com.sun.jndi.ldap.connect.timeout"; + private static final String LDAP_READ_TIMEOUT_KEY = "com.sun.jndi.ldap.read.timeout"; + private static final String SYS_PROP_SSL_KEY_STORE = "javax.net.ssl.keyStore"; + private static final String SYS_PROP_SSL_TRUST_STORE = "javax.net.ssl.trustStore"; + private static final String EXISTING_MOCK_FILE_PATH = String.format("%s/pom.xml", System.getProperty("user.dir")); + private static final LdapBasicAuthenticator AUTHENTICATOR_FOR_UTIL_METHODS_WITHOUT_SSL = new LdapBasicAuthenticator( + getNonSSLPreSettings().setPrincipalTemplate(USERNAME_TEMPLATE) + .setStrategy(STRATEGY_SIMPLE) + .setConnectingTimeout(Duration.parse(CONNECTING_TIMEOUT_VALUE)) + .setReadingTimeout(Duration.parse(READING_TIMEOUT_VALUE)) + ); + private static final LdapBasicAuthenticator AUTHENTICATOR_FOR_UTIL_METHODS_WITH_SSL = new LdapBasicAuthenticator( + getSSLPreSettings().setPrincipalTemplate(USERNAME_TEMPLATE) + .setStrategy(STRATEGY_SIMPLE) + .setCertificateAbsolutePath(EXISTING_MOCK_FILE_PATH) + .setConnectingTimeout(Duration.parse(CONNECTING_TIMEOUT_VALUE)) + .setReadingTimeout(Duration.parse(READING_TIMEOUT_VALUE)) + ); + + @Test + public void testSanitizeUsername() { + String correctUsername = "userNAME_123.45Z"; + String sanitized = AUTHENTICATOR_FOR_UTIL_METHODS_WITHOUT_SSL.sanitizeUsername(correctUsername); + Assert.assertEquals(correctUsername, sanitized); + + String incorrectUsername = "userNAME-~!@#$%^&777*()_+-=`[]\\{}|;':\",./<>?ä½ "; + sanitized = AUTHENTICATOR_FOR_UTIL_METHODS_WITHOUT_SSL.sanitizeUsername(incorrectUsername); + System.out.println(sanitized); + Assert.assertEquals("userNAME777_.", sanitized); + } + + @Test + public void testComprisePrincipal() { + String username = "my.userNAME_123"; + String principal = AUTHENTICATOR_FOR_UTIL_METHODS_WITHOUT_SSL.comprisePrincipal(username); + Assert.assertEquals(username+USERNAME_SUFFIX, principal); + } + + @Test + public void testGetContextEnvironmentNormal() { + String username = "username"; + String secretPhrase = "secret-phrase"; + Hashtable<String, String> env = AUTHENTICATOR_FOR_UTIL_METHODS_WITHOUT_SSL.getContextEnvironment(username, secretPhrase); + + Assert.assertEquals("unexpected ldap context factory name", LDAP_CTX_FACTORY_NAME, env.get(Context.INITIAL_CONTEXT_FACTORY)); + Assert.assertEquals("unexpected ldap service provider url", LDAP_SERVICE_PROVIDER_URL, env.get(Context.PROVIDER_URL)); + Assert.assertEquals("unexpected connecting timeout value", String.valueOf(Duration.parse(CONNECTING_TIMEOUT_VALUE).toMilliseconds()), env.get(LDAP_CONNECT_TIMEOUT_KEY)); + Assert.assertEquals("unexpected reading timeout value", String.valueOf(Duration.parse(READING_TIMEOUT_VALUE).toMilliseconds()), env.get(LDAP_READ_TIMEOUT_KEY)); + Assert.assertEquals("unexpected username", username+USERNAME_SUFFIX, env.get(Context.SECURITY_PRINCIPAL)); + Assert.assertEquals("unexpected secret credentials", secretPhrase, env.get(Context.SECURITY_CREDENTIALS)); + Assert.assertEquals("unexpected strategy", STRATEGY_SIMPLE, env.get(Context.SECURITY_AUTHENTICATION)); + } + + @Test + public void testGetContextEnvironmentBlankStrategy() { + String username = "username"; + String secretPhrase = "secret-phrase"; + + // check strategy while it's configured as "" + LdapBasicAuthenticator blankStrategyAuthenticator = new LdapBasicAuthenticator(getNonSSLPreSettings().setStrategy("")); + String strategyMaybeBlank = blankStrategyAuthenticator.getContextEnvironment(username, secretPhrase).get(Context.SECURITY_AUTHENTICATION); + Assert.assertNull("unexpected strategy", strategyMaybeBlank); + } + + @Test + public void testGetContextEnvironmentNormalWithSSL() { + String username = "username"; + String secretPhrase = "secret-phrase"; + Hashtable<String, String> env = AUTHENTICATOR_FOR_UTIL_METHODS_WITH_SSL.getContextEnvironment(username, secretPhrase); + + Assert.assertEquals("unexpected ldap context factory name", LDAP_CTX_FACTORY_NAME, env.get(Context.INITIAL_CONTEXT_FACTORY)); + Assert.assertEquals("unexpected ldap service provider url", LDAP_SERVICE_PROVIDER_SSL_URL, env.get(Context.PROVIDER_URL)); + Assert.assertEquals("unexpected connecting timeout value", String.valueOf(Duration.parse(CONNECTING_TIMEOUT_VALUE).toMilliseconds()), env.get(LDAP_CONNECT_TIMEOUT_KEY)); + Assert.assertEquals("unexpected reading timeout value", String.valueOf(Duration.parse(READING_TIMEOUT_VALUE).toMilliseconds()), env.get(LDAP_READ_TIMEOUT_KEY)); + Assert.assertEquals("unexpected username", username+USERNAME_SUFFIX, env.get(Context.SECURITY_PRINCIPAL)); + Assert.assertEquals("unexpected secret credentials", secretPhrase, env.get(Context.SECURITY_CREDENTIALS)); + Assert.assertEquals("unexpected strategy", STRATEGY_SIMPLE, env.get(Context.SECURITY_AUTHENTICATION)); + Assert.assertEquals("unexpected key-store path", EXISTING_MOCK_FILE_PATH, System.getProperty(SYS_PROP_SSL_KEY_STORE)); + Assert.assertEquals("unexpected trust-store path", EXISTING_MOCK_FILE_PATH, System.getProperty(SYS_PROP_SSL_TRUST_STORE)); + } + + @Test + public void testGetContextEnvironmentMeaninglessCAPathSSL() { + String username = "username"; + String secretPhrase = "secret-phrase"; + + // check null certificateAbsolutePath + try { + LdapBasicAuthenticator blankStrategyAuthenticator = new LdapBasicAuthenticator(getSSLPreSettings().setCertificateAbsolutePath(null)); + blankStrategyAuthenticator.getContextEnvironment(username, secretPhrase).get(Context.SECURITY_AUTHENTICATION); + } + catch (Exception e) { + Assert.assertEquals("unexpected exception thrown", RuntimeException.class, e.getClass()); + Assert.assertEquals("unexpected exception message", "The attribute 'certificateAbsolutePath' must be set when using ldap over ssl to authenticate.", e.getMessage()); + } + + // check "" certificateAbsolutePath + try { + LdapBasicAuthenticator blankStrategyAuthenticator = new LdapBasicAuthenticator(getSSLPreSettings().setCertificateAbsolutePath("")); + blankStrategyAuthenticator.getContextEnvironment(username, secretPhrase).get(Context.SECURITY_AUTHENTICATION); + } + catch (Exception e) { + Assert.assertEquals("unexpected exception thrown", RuntimeException.class, e.getClass()); + Assert.assertEquals("unexpected exception message", "The attribute 'certificateAbsolutePath' must be set when using ldap over ssl to authenticate.", e.getMessage()); + } + } + + @Test + public void testGetContextEnvironmentUnexistingCA_SSL() { + String username = "username"; + String secretPhrase = "secret-phrase"; + String wrongCAPath = String.format("%s/this/cannot/be/existing", System.getProperty("user.dir")); + try { + // check with not existing path indicated by certificateAbsolutePath + LdapBasicAuthenticator blankStrategyAuthenticator = new LdapBasicAuthenticator(getSSLPreSettings().setCertificateAbsolutePath(wrongCAPath)); + blankStrategyAuthenticator.getContextEnvironment(username, secretPhrase).get(Context.SECURITY_AUTHENTICATION); + } + catch (Exception e) { + Assert.assertEquals("unexpected exception thrown", RuntimeException.class, e.getClass()); + Assert.assertEquals("unexpected exception message", String.format("The file specified not existing: %s", wrongCAPath), e.getMessage()); + } + } + + private static LdapConfig getNonSSLPreSettings() { + return new LdapConfig().setProviderUrl(LDAP_SERVICE_PROVIDER_URL); + } + + private static LdapConfig getSSLPreSettings() { + return new LdapConfig().setProviderUrl(LDAP_SERVICE_PROVIDER_SSL_URL); + } +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-server/src/test/java/org/apache/eagle/server/security/authenticator/SimpleBasicAuthenticatorTest.java ---------------------------------------------------------------------- diff --git a/eagle-server/src/test/java/org/apache/eagle/server/security/authenticator/SimpleBasicAuthenticatorTest.java b/eagle-server/src/test/java/org/apache/eagle/server/security/authenticator/SimpleBasicAuthenticatorTest.java new file mode 100644 index 0000000..8c638c5 --- /dev/null +++ b/eagle-server/src/test/java/org/apache/eagle/server/security/authenticator/SimpleBasicAuthenticatorTest.java @@ -0,0 +1,81 @@ +/* + * 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.eagle.server.security.authenticator; + +import com.google.common.base.Optional; +import io.dropwizard.auth.AuthenticationException; +import io.dropwizard.auth.basic.BasicCredentials; +import org.apache.eagle.common.security.User; +import org.apache.eagle.server.security.config.SimpleConfig; +import org.apache.eagle.server.security.config.UserAccount; +import org.apache.eagle.server.security.encrypt.EncryptorFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collections; + +public class SimpleBasicAuthenticatorTest { + + private static final String TEST_USERNAME = "normal-username"; + private static final String TEST_SECRET_PHRASE = "secret-phrase"; + private static final String TEST_UNEXISTING_USERNAME = "unexisting-username"; + private static final String TEST_WRONG_SECRET_PHRASE = "wrong-secret-phrase"; + + private static SimpleConfig config = new SimpleConfig(); + + static { + config.setAccounts(Collections.singletonList(new UserAccount(TEST_USERNAME, + EncryptorFactory.getPasswordEncryptor().encryptPassword(TEST_SECRET_PHRASE)))); + } + + private static SimpleBasicAuthenticator authenticator = new SimpleBasicAuthenticator(config); + + @Test + public void testNormal() { + try { + BasicCredentials credentials = new BasicCredentials(TEST_USERNAME, TEST_SECRET_PHRASE); + Optional<User> result = authenticator.authenticate(credentials); + Assert.assertTrue("result isn't present when passed correct credentials", result.isPresent()); + User user = result.get(); + Assert.assertEquals("authenticated user is not expected", TEST_USERNAME, user.getName()); + } catch (AuthenticationException e) { + Assert.fail("unexpected error occurs: " + e.getMessage()); + } + } + + @Test + public void testUnexistingUsername() { + try { + Optional<User> result = authenticator.authenticate(new BasicCredentials(TEST_UNEXISTING_USERNAME, TEST_SECRET_PHRASE)); + Assert.assertFalse("result is present when passed unexisting username", result.isPresent()); + } catch (AuthenticationException e) { + Assert.fail("unexpected error occurs: " + e.getMessage()); + } + } + + + @Test + public void testWrongPassword() { + try { + Optional<User> result = authenticator.authenticate(new BasicCredentials(TEST_USERNAME, TEST_WRONG_SECRET_PHRASE)); + Assert.assertFalse("result is present when passed wrong password", result.isPresent()); + } catch (AuthenticationException e) { + Assert.fail("unexpected error occurs: " + e.getMessage()); + } + } +}
