You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by lp...@apache.org on 2017/09/12 10:11:05 UTC
[04/16] ambari git commit: AMBARI-21307 Draft skimplementation for
the user related ldap config attribute validation
AMBARI-21307 Draft skimplementation for the user related ldap config attribute validation
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/031b35e7
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/031b35e7
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/031b35e7
Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 031b35e773b537177040eb2dbdd738aabaa5a69b
Parents: 7014acc
Author: lpuskas <lp...@apache.org>
Authored: Tue Jul 18 17:48:07 2017 +0200
Committer: lpuskas <lp...@apache.org>
Committed: Tue Sep 12 12:07:33 2017 +0200
----------------------------------------------------------------------
ambari-project/pom.xml | 1 +
ambari-server/pom.xml | 7 +-
.../AmbariConfigurationRequestSwagger.java | 1 -
.../services/ldap/AmbariConfigurationDTO.java | 67 +++++++
.../ldap/LdapCheckConfigurationRequest.java | 47 +++++
.../api/services/ldap/LdapOperationRequest.java | 18 ++
.../api/services/ldap/LdapRequestInfo.java | 61 +++++++
.../api/services/ldap/LdapRestService.java | 132 ++++++++++++++
.../ambari/server/controller/AmbariServer.java | 3 +-
.../server/controller/ControllerModule.java | 1 +
.../server/ldap/AmbariLdapConfiguration.java | 129 ++++++++++++++
.../server/ldap/LdapConfigurationFactory.java | 21 +++
.../ldap/LdapConfigurationValidatorService.java | 52 ++++++
.../apache/ambari/server/ldap/LdapModule.java | 37 ++++
.../ldap/service/AmbariLdapException.java | 33 ++++
.../server/ldap/service/AmbariLdapFacade.java | 107 +++++++++++
.../ambari/server/ldap/service/LdapFacade.java | 52 ++++++
.../server/ldap/service/LdapSearchService.java | 18 ++
.../ad/AdLdapConfigurationValidatorService.java | 177 +++++++++++++++++++
.../service/ad/LdapConfigurationConverter.java | 50 ++++++
.../api/services/ldap/LDAPServiceTest.java | 85 +++++++++
...AdLdapConfigurationValidatorServiceTest.java | 129 ++++++++++++++
22 files changed, 1224 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-project/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-project/pom.xml b/ambari-project/pom.xml
index 00ba1bc..e4d4423 100644
--- a/ambari-project/pom.xml
+++ b/ambari-project/pom.xml
@@ -31,6 +31,7 @@
<ambari.dir>${project.parent.basedir}</ambari.dir>
<powermock.version>1.6.3</powermock.version>
<jetty.version>8.1.19.v20160209</jetty.version>
+ <ldap-api.version>1.0.0</ldap-api.version>
<checkstyle.version>6.19</checkstyle.version> <!-- last version that does not require Java 8 -->
<swagger.version>1.5.10</swagger.version>
<swagger.maven.plugin.version>3.1.4</swagger.maven.plugin.version>
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index 29a820a..c0f30be 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -1287,7 +1287,6 @@
<dependency>
<groupId>org.apache.directory.shared</groupId>
<artifactId>shared-ldap</artifactId>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@@ -1686,8 +1685,12 @@
<artifactId>jna</artifactId>
<version>4.2.2</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.directory.api</groupId>
+ <artifactId>api-all</artifactId>
+ <version>${ldap-api.version}</version>
+ </dependency>
</dependencies>
-
<pluginRepositories>
<pluginRepository>
<id>oss.sonatype.org</id>
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
index d6714f9..5e8094e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
@@ -16,7 +16,6 @@ package org.apache.ambari.server.api.services;
import java.util.Map;
import org.apache.ambari.server.controller.ApiModel;
-import org.apache.ambari.server.orm.entities.ConfigurationBaseEntity;
import io.swagger.annotations.ApiModelProperty;
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java
new file mode 100644
index 0000000..1b134fe
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfigurationDTO.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed 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.server.api.services.ldap;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+public class AmbariConfigurationDTO {
+ private String type;
+ private Set<Map<String, Object>> data = Collections.emptySet();
+ private String versionTag;
+ private Integer version;
+ private long createdTs;
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public Set<Map<String, Object>> getData() {
+ return data;
+ }
+
+ public void setData(Set<Map<String, Object>> data) {
+ this.data = data;
+ }
+
+ public String getVersionTag() {
+ return versionTag;
+ }
+
+ public void setVersionTag(String versionTag) {
+ this.versionTag = versionTag;
+ }
+
+ public Integer getVersion() {
+ return version;
+ }
+
+ public void setVersion(Integer version) {
+ this.version = version;
+ }
+
+ public long getCreatedTs() {
+ return createdTs;
+ }
+
+ public void setCreatedTs(long createdTs) {
+ this.createdTs = createdTs;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java
new file mode 100644
index 0000000..188f1b9
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapCheckConfigurationRequest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed 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.server.api.services.ldap;
+
+
+import com.google.gson.annotations.SerializedName;
+
+public class LdapCheckConfigurationRequest implements LdapOperationRequest {
+
+ @SerializedName("AmbariConfiguration")
+ private AmbariConfigurationDTO ambariConfiguration;
+
+ @SerializedName("RequestInfo")
+ private LdapRequestInfo requestInfo;
+
+ public LdapCheckConfigurationRequest() {
+ }
+
+
+ public AmbariConfigurationDTO getAmbariConfiguration() {
+ return ambariConfiguration;
+ }
+
+ public void setAmbariConfiguration(AmbariConfigurationDTO ambariConfiguration) {
+ this.ambariConfiguration = ambariConfiguration;
+ }
+
+ public LdapRequestInfo getRequestInfo() {
+ return requestInfo;
+ }
+
+ public void setRequestInfo(LdapRequestInfo requestInfo) {
+ this.requestInfo = requestInfo;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java
new file mode 100644
index 0000000..06f6c40
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapOperationRequest.java
@@ -0,0 +1,18 @@
+/*
+ * Licensed 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.server.api.services.ldap;
+
+public interface LdapOperationRequest {
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
new file mode 100644
index 0000000..eeecfee
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed 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.server.api.services.ldap;
+
+import java.util.Map;
+
+import org.apache.ambari.server.controller.RequestPostRequest;
+
+/**
+ * Bean holding LDAP request specific request information.
+ */
+public class LdapRequestInfo implements RequestPostRequest.RequestInfo {
+
+ // no-arg costructor facilitating JSON serialization
+ public LdapRequestInfo() {
+ }
+
+ private String action;
+
+ private Map<String, Object> parameters;
+
+ @Override
+ public String getAction() {
+ return action;
+ }
+
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public void setParameters(Map<String, Object> parameters) {
+ this.parameters = parameters;
+ }
+
+ @Override
+ public String getCommand() {
+ return null;
+ }
+
+ @Override
+ public RequestPostRequest.OperationLevel getOperationLevel() {
+ return null;
+ }
+
+ @Override
+ public Map<String, Object> getParameters() {
+ return parameters;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
new file mode 100644
index 0000000..33b10fa
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRestService.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed 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.
+ */
+
+/*
+ * Licensed 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.server.api.services.ldap;
+
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.ambari.annotations.ApiIgnore;
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.api.services.BaseService;
+import org.apache.ambari.server.api.services.Result;
+import org.apache.ambari.server.api.services.ResultImpl;
+import org.apache.ambari.server.api.services.ResultStatus;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationFactory;
+import org.apache.ambari.server.ldap.service.LdapFacade;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Endpoint designated to LDAP specific operations.
+ */
+@StaticallyInject
+@Path("/ldap")
+public class LdapRestService extends BaseService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(LdapRestService.class);
+
+ @Inject
+ private static LdapFacade ldapFacade;
+
+ @Inject
+ private static LdapConfigurationFactory ldapConfigurationFactory;
+
+ @POST
+ @ApiIgnore // until documented
+ @Path("/action") // todo this needs to be moved under the resource
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response validateConfiguration(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
+
+ Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
+ try {
+
+ validateRequest(ldapCheckConfigurationRequest);
+
+ AmbariLdapConfiguration ambariLdapConfiguration = ldapConfigurationFactory.createLdapConfiguration(
+ ldapCheckConfigurationRequest.getAmbariConfiguration().getData().iterator().next());
+
+ switch (ldapCheckConfigurationRequest.getRequestInfo().getAction()) {
+ case "test-connection":
+
+ LOGGER.info("Testing connection to the LDAP server ...");
+ ldapFacade.checkConnection(ambariLdapConfiguration);
+
+ break;
+ case "test-attributes":
+
+ LOGGER.info("Testing LDAP attributes ....");
+ ldapFacade.checkLdapAttibutes(ldapCheckConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
+
+ break;
+ case "detect-attributes":
+
+ LOGGER.info("Detecting LDAP attributes ...");
+ ldapFacade.detectAttributes(ambariLdapConfiguration);
+
+ break;
+ default:
+ LOGGER.warn("No action provided ...");
+ throw new IllegalArgumentException("No request action provided");
+ }
+
+ } catch (Exception e) {
+ result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e));
+ }
+
+ return Response.status(result.getStatus().getStatusCode()).entity(getResultSerializer().serialize(result)).build();
+ }
+
+ private void validateRequest(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) {
+ String errMsg;
+
+ if (null == ldapCheckConfigurationRequest) {
+ errMsg = "No ldap configuraiton request provided";
+ LOGGER.error(errMsg);
+ throw new IllegalArgumentException(errMsg);
+ }
+
+ if (null == ldapCheckConfigurationRequest.getRequestInfo()) {
+ errMsg = String.format("No request information provided. Request: [%s]", ldapCheckConfigurationRequest);
+ LOGGER.error(errMsg);
+ throw new IllegalArgumentException(errMsg);
+ }
+
+ if (null == ldapCheckConfigurationRequest.getAmbariConfiguration()
+ || ldapCheckConfigurationRequest.getAmbariConfiguration().getData().size() != 1) {
+ errMsg = String.format("No / Invalid configuration data provided. Request: [%s]", ldapCheckConfigurationRequest);
+ LOGGER.error(errMsg);
+ throw new IllegalArgumentException(errMsg);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 8988be0..6ceed4a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -77,6 +77,7 @@ import org.apache.ambari.server.controller.internal.ViewPermissionResourceProvid
import org.apache.ambari.server.controller.metrics.ThreadPoolEnabledPropertyProvider;
import org.apache.ambari.server.controller.utilities.KerberosChecker;
import org.apache.ambari.server.controller.utilities.KerberosIdentityCleaner;
+import org.apache.ambari.server.ldap.LdapModule;
import org.apache.ambari.server.metrics.system.MetricsService;
import org.apache.ambari.server.orm.GuiceJpaInitializer;
import org.apache.ambari.server.orm.PersistenceType;
@@ -1061,7 +1062,7 @@ public class AmbariServer {
public static void main(String[] args) throws Exception {
logStartup();
- Injector injector = Guice.createInjector(new ControllerModule(), new AuditLoggerModule());
+ Injector injector = Guice.createInjector(new ControllerModule(), new AuditLoggerModule(), new LdapModule());
AmbariServer server = null;
try {
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index edabcdb..bf790a7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -504,6 +504,7 @@ public class ControllerModule extends AbstractModule {
install(new FactoryModuleBuilder().implement(CollectionPersisterService.class, CsvFilePersisterService.class).build(CollectionPersisterServiceFactory.class));
install(new FactoryModuleBuilder().build(ConfigureClusterTaskFactory.class));
+
}
/**
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
new file mode 100644
index 0000000..519f400
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/AmbariLdapConfiguration.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed 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.server.ldap;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.assistedinject.Assisted;
+
+/**
+ * This class is an immutable representation of all the LDAP related configurationMap entries.
+ */
+@Singleton
+public class AmbariLdapConfiguration {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AmbariLdapConfiguration.class);
+
+ /**
+ * Constants representing supported LDAP related property names
+ */
+ public enum LdapConfigProperty {
+ LDAP_CONFIGURED("ambari.ldap.configured"),
+ AUTOMATIC_ATTRIBUTE_DETECTION("ambari.ldap.automatic.attribute.detection"),
+
+ USE_SSL("ambari.ldap.usessl"),
+ LDAP_SERVER_HOST("ambari.ldap.server.host"),
+ LDAP_SERVER_PORT("ambari.ldap.server.port"),
+ BASE_DN("ambari.ldap.base.dn"),
+
+ BIND_ANONIMOUSLY("ambari.ldap.bindanonymously"),
+ MANAGER_DN("ambari.ldap.managerdn"),
+ MANAGER_PASSWORD("ambari.ldap.managerpassword"),
+ USER_OBJECT_CLASS("ambari.ldap.user.object.class"),
+ USER_NAME_ATTRIBUTE("ambari.ldap.user.name.attribute"),
+ USER_SEARCH_BASE("ambari.ldap.user.search.Base"),
+
+ GROUP_OBJECT_CLASS("ambari.ldap.group.object.class"),
+ GROUP_NAME_ATTRIBUTE("ambari.ldap.group.name.attribute"),
+ GROUP_MEMBER_ATTRIBUTE("ambari.ldap.group.member.attribute"),
+ GROUP_SEARCH_BASE("ambari.ldap.group.member.attribute"),
+ DN_ATTRIBUTE("authentication.ldap.dnAttribute");
+
+ private String propertyName;
+
+ LdapConfigProperty(String propertyName) {
+ this.propertyName = propertyName;
+ }
+
+ public String propertyName() {
+ return this.propertyName;
+ }
+ }
+
+ private final Map<String, Object> configurationMap;
+
+ private Object configurationValue(LdapConfigProperty ldapConfigProperty) {
+ Object value = null;
+ if (configurationMap.containsKey(ldapConfigProperty.propertyName)) {
+ value = configurationMap.get(ldapConfigProperty.propertyName);
+ } else {
+ LOGGER.warn("Ldap configuration property [{}] hasn't been set", ldapConfigProperty.propertyName());
+ }
+
+ return value;
+ }
+
+ @Inject
+ public AmbariLdapConfiguration(@Assisted Map<String, Object> configuration) {
+ this.configurationMap = configuration;
+ }
+
+
+ public String ldapServerHost() {
+ return (String) configurationValue(LdapConfigProperty.LDAP_SERVER_HOST);
+ }
+
+ public int ldapServerPort() {
+ return Integer.valueOf((String) configurationValue(LdapConfigProperty.LDAP_SERVER_PORT));
+ }
+
+ public boolean useSSL() {
+ return Boolean.valueOf((String) configurationValue(LdapConfigProperty.USE_SSL));
+ }
+
+ public boolean bindAnonimously() {
+ return Boolean.valueOf((String) configurationValue(LdapConfigProperty.BIND_ANONIMOUSLY));
+ }
+
+ public String managerDn() {
+ return (String) configurationValue(LdapConfigProperty.MANAGER_DN);
+ }
+
+ public String managerPassword() {
+ return (String) configurationValue(LdapConfigProperty.MANAGER_PASSWORD);
+ }
+
+ public boolean automaticAttributeDetection() {
+ return Boolean.valueOf((String) configurationValue(LdapConfigProperty.AUTOMATIC_ATTRIBUTE_DETECTION));
+ }
+
+ public String baseDn() {
+ return (String) configurationValue(LdapConfigProperty.BASE_DN);
+ }
+
+ public String userObjectClass() {
+ return (String) configurationValue(LdapConfigProperty.USER_OBJECT_CLASS);
+ }
+
+ public String userNameAttribute() {
+ return (String) configurationValue(LdapConfigProperty.USER_NAME_ATTRIBUTE);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java
new file mode 100644
index 0000000..bcd6e39
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationFactory.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed 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.server.ldap;
+
+import java.util.Map;
+
+public interface LdapConfigurationFactory {
+ AmbariLdapConfiguration createLdapConfiguration(Map<String, Object> configuration);
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
new file mode 100644
index 0000000..4667721
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapConfigurationValidatorService.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed 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.server.ldap;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.service.AmbariLdapException;
+
+/**
+ * Collection of operations for validating ldap configuration.
+ * It's intended to decouple implementations using different libraries.
+ */
+public interface LdapConfigurationValidatorService {
+
+ /**
+ * Tests the connection based on the provided configuration.
+ *
+ * @param configuration the ambari ldap configuration instance
+ * @throws AmbariLdapException if the connection is not possible
+ */
+ void checkConnection(AmbariLdapConfiguration configuration) throws AmbariLdapException;
+
+ /**
+ * Checks whether the group related LDAP attributes in the configuration are correct.
+ *
+ * @param configuration the configuration instance holding the available properties
+ * @throws AmbariException if the attributes are not valid
+ */
+ void checkGroupAttributes(AmbariLdapConfiguration configuration) throws AmbariException;
+
+ /**
+ * Tries to connect to the LDAP server with the given credentials.
+ * Primarily used for testing the user before performing other operations (eg. attribute detection)s
+ *
+ * @param username the username
+ * @param password the password
+ * @param configuration the available ldap configuration
+ * @throws AmbariException if the connection couldn't be estabilished
+ */
+ void checkUserAttributes(String username, String password, AmbariLdapConfiguration configuration) throws AmbariException;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
new file mode 100644
index 0000000..625ce8b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed 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.server.ldap;
+
+import org.apache.ambari.server.ldap.service.AmbariLdapFacade;
+import org.apache.ambari.server.ldap.service.LdapFacade;
+import org.apache.ambari.server.ldap.service.ad.AdLdapConfigurationValidatorService;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
+
+/**
+ * GUICE configuration module for setting up LDAP related infrastructure.
+ */
+public class LdapModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ bind(LdapFacade.class).to(AmbariLdapFacade.class);
+ bind(LdapConfigurationValidatorService.class).to(AdLdapConfigurationValidatorService.class);
+
+ install(new FactoryModuleBuilder().build(LdapConfigurationFactory.class));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapException.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapException.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapException.java
new file mode 100644
index 0000000..cb38acc
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapException.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed 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.server.ldap.service;
+
+public class AmbariLdapException extends Exception {
+ public AmbariLdapException() {
+ super();
+ }
+
+ public AmbariLdapException(String message) {
+ super(message);
+ }
+
+ public AmbariLdapException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public AmbariLdapException(Throwable cause) {
+ super(cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
new file mode 100644
index 0000000..abd028a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed 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.server.ldap.service;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class AmbariLdapFacade implements LdapFacade {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AmbariLdapFacade.class);
+
+ private enum Parameters {
+ TEST_USER_NAME("ldap.test.user.name"),
+ TEST_USER_PASSWORD("ldap.test.user.password");
+
+ private String parameterKey;
+
+ Parameters(String parameterKey) {
+ this.parameterKey = parameterKey;
+ }
+
+ private String getParameterKey() {
+ return parameterKey;
+ }
+
+ }
+
+ @Inject
+ private LdapConfigurationValidatorService ldapConfigurationValidatorService;
+
+ @Inject
+ public AmbariLdapFacade() {
+ }
+
+ @Override
+ public void checkConnection(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException {
+ try {
+ LOGGER.info("Validating LDAP connection related configuration based on: {}", ambariLdapConfiguration);
+ ldapConfigurationValidatorService.checkConnection(ambariLdapConfiguration);
+ } catch (AmbariLdapException e) {
+ LOGGER.error("Validating LDAP connection configuration failed", e);
+ throw new AmbariException("Validating LDAP connection configuration failed", e);
+ }
+ LOGGER.info("Validating LDAP connection related configuration: SUCCESS");
+ }
+
+
+ @Override
+ public void detectAttributes(AmbariLdapConfiguration ambariLdapConfiguration) {
+ LOGGER.info("Detecting LDAP configuration attributes ...");
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ @Override
+ public void checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ldapConfiguration) throws AmbariException {
+ String userName = getTestUserNameFromParameters(parameters);
+ String testUserPass = getTestUserPasswordFromParameters(parameters);
+
+ if (null == userName) {
+ throw new IllegalArgumentException("No test user available for testing LDAP attributes");
+ }
+
+ LOGGER.info("Testing LDAP attributes with test user: {}", userName);
+ ldapConfigurationValidatorService.checkUserAttributes(userName, testUserPass, ldapConfiguration);
+ }
+
+
+ private String getTestUserNameFromParameters(Map<String, Object> parameters) {
+ return (String) parameterValue(parameters, Parameters.TEST_USER_NAME);
+ }
+
+ private String getTestUserPasswordFromParameters(Map<String, Object> parameters) {
+ return (String) parameterValue(parameters, Parameters.TEST_USER_PASSWORD);
+ }
+
+ private Object parameterValue(Map<String, Object> parameters, Parameters parameter) {
+ Object value = null;
+ if (parameters.containsKey(parameter.getParameterKey())) {
+ value = parameters.get(parameter.getParameterKey());
+ } else {
+ LOGGER.warn("Parameter [{}] is missing from parameters", parameter.getParameterKey());
+ }
+ return value;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
new file mode 100644
index 0000000..38553f0
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed 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.server.ldap.service;
+
+import java.util.Map;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+
+/**
+ * The contract defining all the operations required by the application when communicating with an arbitrary LDAP server.
+ * This interface is intended to decouple LDAP specific details from the application.
+ */
+public interface LdapFacade {
+
+ /**
+ * Tests the connection to the LDAP server based on the provided configuration.
+ *
+ * @param ambariLdapConfiguration the available ldap related configuration
+ * @throws AmbariException if the connection fails or other problems occur during the operation
+ */
+ void checkConnection(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException;
+
+
+ /**
+ * Runs the user and group attribute detection algorithms
+ *
+ * @param ambariLdapConfiguration
+ */
+ void detectAttributes(AmbariLdapConfiguration ambariLdapConfiguration);
+
+ /**
+ * Checks user and group related LDAP configuration attributes in the configuration object with the help of the provided parameters
+ *
+ * @param parameters a map of property name and value pairs holding information to facilitate checking the attributes
+ * @param ambariLdapConfiguration configutration instance with available attributes
+ * @throws AmbariException if the attribute checking fails
+ */
+ void checkLdapAttibutes(Map<String, Object> parameters, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java
new file mode 100644
index 0000000..f1abc8b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapSearchService.java
@@ -0,0 +1,18 @@
+/*
+ * Licensed 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.server.ldap.service;
+
+public interface LdapSearchService {
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java
new file mode 100644
index 0000000..11e8655
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorService.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed 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.server.ldap.service.ad;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.apache.ambari.server.ldap.service.AmbariLdapException;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Implementation of the validation logic using the Apache Directory API.
+ */
+@Singleton
+public class AdLdapConfigurationValidatorService implements LdapConfigurationValidatorService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AdLdapConfigurationValidatorService.class);
+
+ @Inject
+ private LdapConfigurationConverter ldapConfigurationConverter;
+
+ /**
+ * Facilitating the instantiation
+ */
+ @Inject
+ public AdLdapConfigurationValidatorService() {
+ }
+
+ @Override
+ public void checkConnection(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException {
+ try {
+ LOGGER.info("Testing the connection based on the configuration: {}", ambariLdapConfiguration);
+
+ LdapConnectionConfig connectionConfig = ldapConfigurationConverter.getLdapConnectionConfig(ambariLdapConfiguration);
+ LdapNetworkConnection connection = new LdapNetworkConnection(connectionConfig);
+
+ if (ambariLdapConfiguration.bindAnonimously()) {
+ LOGGER.debug("Binding anonimously ...");
+ connection.bind();
+ } else {
+ LOGGER.debug("Binding with manager DN and manager password ...");
+ connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
+ }
+
+ if (connection.isConnected()) {
+ LOGGER.info("Successfully connected to the LDAP server.");
+ }
+
+ connection.close();
+
+ } catch (Exception e) {
+ LOGGER.warn("Could not bind to the LDAP server base don the provided configuration ...");
+ throw new AmbariLdapException(e);
+ }
+ }
+
+
+ /**
+ * Checks the user attributes provided in the configuration instance by issuing a search for a (known) test user in the LDAP.
+ * Attributes are considered correct if there is at least one entry found.
+ *
+ * Invalid attributes are signaled by throwing an exception.
+ *
+ * @param username the username
+ * @param password the password
+ * @param ambariLdapConfiguration configuration instance holding ldap configuration details
+ * @throws AmbariException if the attributes are not valid or any errors occurs
+ */
+ @Override
+ public void checkUserAttributes(String username, String password, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariException {
+ LdapNetworkConnection connection = null;
+ SearchCursor searchCursor = null;
+ try {
+ LOGGER.info("Checking user attributes for user {} r ...", username);
+
+ LdapConnectionConfig connectionConfig = ldapConfigurationConverter.getLdapConnectionConfig(ambariLdapConfiguration);
+ connection = new LdapNetworkConnection(connectionConfig);
+
+
+ if (!ambariLdapConfiguration.bindAnonimously()) {
+ LOGGER.debug("Anonimous binding not supported, binding with the manager detailas...");
+ connection.bind(ambariLdapConfiguration.managerDn(), ambariLdapConfiguration.managerPassword());
+ } else {
+ LOGGER.debug("Binding anonimously ...");
+ connection.bind();
+ }
+
+ if (!connection.isConnected()) {
+ LOGGER.error("Not connected to the LDAP server. Connection instance: {}", connection);
+ throw new IllegalStateException("The connection to the LDAP server is not alive");
+ }
+
+ // set up a filter based on the provided attributes
+ String filter = FilterBuilder.and(
+ FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
+ FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), username))
+ .toString();
+
+ LOGGER.info("Searching for the user: {} using the search filter: {}", username, filter);
+ EntryCursor entryCursor = connection.search(new Dn(ambariLdapConfiguration.baseDn()), filter, SearchScope.SUBTREE);
+
+ // collecting search result entries
+ List<Entry> users = Lists.newArrayList();
+ for (Entry entry : entryCursor) {
+ users.add(entry);
+ }
+
+ // there should be at least one user found
+ if (users.isEmpty()) {
+ String msg = String.format("There are no users found using the filter: [ %s ]. Try changing the attribute values", filter);
+ LOGGER.error(msg);
+ throw new Exception(msg);
+ }
+
+ LOGGER.info("Attibute validation succeeded. Filter: {}", filter);
+
+ } catch (Exception e) {
+
+ LOGGER.error("Error while checking user attributes.");
+ throw new AmbariException("Error while checking user attributes", e);
+
+ } finally {
+
+ LOGGER.debug("Closing the connection and searchresult ...");
+
+ if (null != searchCursor) {
+ searchCursor.close();
+ }
+
+ if (null != connection) {
+ try {
+ connection.close();
+ } catch (IOException e) {
+ LOGGER.error("Exception occurred while closing the connection", e);
+ }
+ }
+
+ }
+ }
+
+ @Override
+ public void checkGroupAttributes(AmbariLdapConfiguration configuration) throws AmbariException {
+
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java
new file mode 100644
index 0000000..a8839f1
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/LdapConfigurationConverter.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed 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.server.ldap.service.ad;
+
+import javax.inject.Singleton;
+
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Converts between ambari specific ldap types and the 3rd party ldap library
+ */
+@Singleton
+public class LdapConfigurationConverter {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(LdapConfigurationConverter.class);
+
+ /**
+ * Creates a {@link LdapConnectionConfig} instance based on the provided ambari specific configurations
+ *
+ * @param ambariAmbariLdapConfiguration
+ * @return
+ */
+ public LdapConnectionConfig getLdapConnectionConfig(AmbariLdapConfiguration ambariAmbariLdapConfiguration) {
+ LOGGER.debug("Creating a configuration instance based on the ambari configuration: {}", ambariAmbariLdapConfiguration);
+
+ LdapConnectionConfig ldapConnectionConfig = new LdapConnectionConfig();
+ ldapConnectionConfig.setLdapHost(ambariAmbariLdapConfiguration.ldapServerHost());
+ ldapConnectionConfig.setLdapPort(ambariAmbariLdapConfiguration.ldapServerPort());
+ ldapConnectionConfig.setUseSsl(ambariAmbariLdapConfiguration.useSSL());
+
+ //todo set the other values as required
+ return ldapConnectionConfig;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java
new file mode 100644
index 0000000..f20cd1f
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ldap/LDAPServiceTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed 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.server.api.services.ldap;
+
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public class LDAPServiceTest {
+
+ private static String JSON_STRING = "{\n" +
+ " \"AmbariConfiguration\": {\n" +
+ " \"type\": \"ldap-config\",\n" +
+ " \"data\": [{\n" +
+ " \"authentication.ldap.primaryUrl\": \"localhost:33389\",\n" +
+ " \"authentication.ldap.secondaryUrl\": \"localhost:333\",\n" +
+ " \"authentication.ldap.baseDn\": \"dc=ambari,dc=apache,dc=org\"\n" +
+ " }]\n" +
+ " }\n" +
+ "}";
+
+ @Test
+ public void testJaxRsJsonTransformation() throws Exception {
+ // GIVEN
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ Gson gsonJsonProvider = new GsonBuilder().create();
+
+
+ // WHEN
+ LdapCheckConfigurationRequest ldapCheckConfigurationRequest = gsonJsonProvider.fromJson(JSON_STRING, LdapCheckConfigurationRequest.class);
+ // LdapCheckConfigurationRequest ldapCheckConfigurationRequest = objectMapper.readValue(JSON_STRING, LdapCheckConfigurationRequest.class);
+
+ // THEN
+ Assert.assertNotNull(ldapCheckConfigurationRequest);
+
+ }
+
+
+ @Test
+ public void testLdapConnection() throws Exception {
+ // GIVEN
+ LdapConnection connection = new LdapNetworkConnection("localhost", 389);
+
+ // WHEN
+ connection.bind();
+ // THEN
+
+ }
+
+
+ @Test
+ public void testLdapConnectionConfigs() throws Exception {
+ // GIVEN
+ LdapConnectionConfig config = new LdapConnectionConfig();
+ config.setLdapHost("localhost");
+ config.setLdapPort(389);
+
+ // WHEN
+ LdapConnection connection = new LdapNetworkConnection(config);
+
+ // THEN
+ connection.anonymousBind();
+
+ Assert.assertNotNull(connection);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/031b35e7/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java
new file mode 100644
index 0000000..0f57099
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/AdLdapConfigurationValidatorServiceTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed 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.server.ldap.service.ad;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ldap.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.LdapConfigurationValidatorService;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.message.Response;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchResultEntry;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public class AdLdapConfigurationValidatorServiceTest {
+ private static final Logger LOGGER = LoggerFactory.getLogger(AdLdapConfigurationValidatorService.class);
+ private static final String TEST_USER = "Jocika10";
+
+ LdapConfigurationValidatorService ldapConfigurationValidatorService = new AdLdapConfigurationValidatorService();
+
+
+ @Test
+ public void testCheckAttributes() throws Exception {
+
+ // WHEN
+ LdapConnectionConfig config = new LdapConnectionConfig();
+ config.setLdapHost("localhost");
+ config.setLdapPort(389);
+ LdapConnection connection = new LdapNetworkConnection(config);
+
+ // THEN
+ connection.anonymousBind();
+
+
+ EntryCursor cursor = connection.search("dc=dev,dc=local", "(objectclass=*)", SearchScope.ONELEVEL);
+
+ for (Entry entry : cursor) {
+ assertNotNull(entry);
+ System.out.println(entry);
+ }
+
+ cursor.close();
+
+ }
+
+ @Test
+ public void testCheckUserAttributes() throws Exception {
+ Map<String, Object> ldapPropsMap = Maps.newHashMap();
+
+ ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), true);
+ ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "localhost");
+ ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389");
+ ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=dev,dc=local");
+ ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC);
+ ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT);
+
+ AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap);
+
+
+ try {
+ LOGGER.info("Authenticating user {} against the LDAP server ...", TEST_USER);
+ LdapConfigurationConverter ldapConfigurationConverter = new LdapConfigurationConverter();
+
+ LdapConnectionConfig connectionConfig = ldapConfigurationConverter.getLdapConnectionConfig(ambariLdapConfiguration);
+ LdapNetworkConnection connection = new LdapNetworkConnection(connectionConfig);
+
+ String filter = FilterBuilder.and(
+ FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.userObjectClass()),
+ FilterBuilder.equal(ambariLdapConfiguration.userNameAttribute(), TEST_USER))
+ .toString();
+
+ SearchRequest searchRequest = new SearchRequestImpl();
+ searchRequest.setBase(new Dn(ambariLdapConfiguration.baseDn()));
+ searchRequest.setFilter(filter);
+ searchRequest.setScope(SearchScope.SUBTREE);
+
+ LOGGER.info("loking up user: {} based on the filtr: {}", TEST_USER, filter);
+
+ connection.bind();
+ SearchCursor searchCursor = connection.search(searchRequest);
+
+ while (searchCursor.next()) {
+ Response response = searchCursor.get();
+
+ // process the SearchResultEntry
+ if (response instanceof SearchResultEntry) {
+ Entry resultEntry = ((SearchResultEntry) response).getEntry();
+ System.out.println(resultEntry);
+ }
+ }
+
+ searchCursor.close();
+
+ } catch (Exception e) {
+ throw new AmbariException("Error during user authentication check", e);
+ }
+
+ }
+
+}
\ No newline at end of file