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/5e01dc8c
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/5e01dc8c
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/5e01dc8c

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 5e01dc8c6983b3e3fb138e5dfd1d774f7d385515
Parents: a1c9adb
Author: lpuskas <lpus...@apache.org>
Authored: Tue Jul 18 17:48:07 2017 +0200
Committer: lpuskas <lpus...@apache.org>
Committed: Thu Oct 12 19:25:48 2017 +0200

----------------------------------------------------------------------
 ambari-project/pom.xml                          |   1 +
 ambari-server/pom.xml                           |   5 +
 .../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(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/5e01dc8c/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/5e01dc8c/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index e250da7..8d52821 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -1689,6 +1689,11 @@
       <version>4.2.2</version>
     </dependency>
     <dependency>
+      <groupId>org.apache.directory.api</groupId>
+      <artifactId>api-all</artifactId>
+      <version>${ldap-api.version}</version>
+    </dependency>
+    <dependency>
       <groupId>com.networknt</groupId>
       <artifactId>json-schema-validator</artifactId>
       <version>0.1.10</version>

http://git-wip-us.apache.org/repos/asf/ambari/blob/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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 b79d122..4f30b15 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
@@ -510,6 +510,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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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/5e01dc8c/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

Reply via email to