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/10/30 15:21:33 UTC

[13/13] ambari git commit: AMBARI-21307 Feature for supporting LDAP configuration from the UI

AMBARI-21307 Feature for supporting LDAP configuration from the UI


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/6b7a7a70
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/6b7a7a70
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/6b7a7a70

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: 6b7a7a706d6e4d8c4a5e0300666e56f6704eb00a
Parents: 9d6ac96
Author: lpuskas <lp...@apache.org>
Authored: Wed Jul 5 14:20:18 2017 +0200
Committer: lpuskas <lp...@apache.org>
Committed: Mon Oct 30 16:33:57 2017 +0200

----------------------------------------------------------------------
 ambari-funtest/pom.xml                          |  67 ----
 ambari-project/pom.xml                          |  52 +--
 ambari-server/pom.xml                           |  83 +----
 .../resources/ResourceInstanceFactoryImpl.java  |   4 +
 .../AmbariConfigurationRequestSwagger.java      |  47 +++
 .../AmbariConfigurationResponseSwagger.java     |  40 +++
 .../services/AmbariConfigurationService.java    | 193 +++++++++++
 .../api/services/ldap/AmbariConfiguration.java  |  87 +++++
 .../api/services/ldap/LdapConfigOperation.java  |  43 +++
 .../services/ldap/LdapConfigurationRequest.java |  49 +++
 .../services/ldap/LdapConfigurationService.java | 185 +++++++++++
 .../api/services/ldap/LdapRequestInfo.java      |  61 ++++
 .../stackadvisor/StackAdvisorRequest.java       |  12 +
 .../commands/StackAdvisorCommand.java           |  54 +++
 .../ambari/server/controller/AmbariServer.java  |   3 +-
 .../server/controller/ControllerModule.java     |   3 +
 .../controller/ResourceProviderFactory.java     |  24 +-
 .../AbstractControllerResourceProvider.java     |   2 +
 .../internal/AbstractProviderModule.java        |   2 +-
 .../AmbariConfigurationResourceProvider.java    | 328 +++++++++++++++++++
 .../internal/DefaultProviderModule.java         |  24 +-
 .../ambari/server/controller/spi/Resource.java  |   5 +-
 .../ambari/server/events/AmbariEvent.java       |  11 +-
 .../events/AmbariLdapConfigChangedEvent.java    |  37 +++
 .../apache/ambari/server/ldap/LdapModule.java   |  82 +++++
 .../ldap/domain/AmbariLdapConfigKeys.java       |  83 +++++
 .../ldap/domain/AmbariLdapConfiguration.java    | 199 +++++++++++
 .../domain/AmbariLdapConfigurationFactory.java  |  34 ++
 .../AmbariLdapConfigurationProvider.java        | 120 +++++++
 .../ldap/service/AmbariLdapException.java       |  33 ++
 .../server/ldap/service/AmbariLdapFacade.java   | 140 ++++++++
 .../server/ldap/service/AttributeDetector.java  |  41 +++
 .../service/LdapAttributeDetectionService.java  |  40 +++
 .../ldap/service/LdapConfigurationService.java  |  60 ++++
 .../service/LdapConnectionConfigService.java    |  36 ++
 .../ambari/server/ldap/service/LdapFacade.java  |  58 ++++
 .../DefaultLdapAttributeDetectionService.java   | 200 +++++++++++
 .../ads/DefaultLdapConfigurationService.java    | 213 ++++++++++++
 .../ads/DefaultLdapConnectionConfigService.java | 113 +++++++
 .../ads/LdapConnectionTemplateFactory.java      | 111 +++++++
 .../ads/detectors/AttributeDetectorFactory.java |  75 +++++
 .../ads/detectors/ChainedAttributeDetector.java |  73 +++++
 .../ads/detectors/GroupMemberAttrDetector.java  |  65 ++++
 .../ads/detectors/GroupNameAttrDetector.java    |  70 ++++
 .../ads/detectors/GroupObjectClassDetector.java |  73 +++++
 .../OccurrenceAndWeightBasedDetector.java       | 143 ++++++++
 .../detectors/UserGroupMemberAttrDetector.java  |  64 ++++
 .../ads/detectors/UserNameAttrDetector.java     |  71 ++++
 .../ads/detectors/UserObjectClassDetector.java  |  69 ++++
 .../server/orm/dao/AmbariConfigurationDAO.java  |  89 +++++
 .../apache/ambari/server/orm/dao/DaoUtils.java  |  13 +-
 .../orm/entities/AmbariConfigurationEntity.java |  70 ++++
 .../orm/entities/ConfigurationBaseEntity.java   | 159 +++++++++
 .../authorization/RoleAuthorization.java        |  95 +++---
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |  21 ++
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  20 ++
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  20 ++
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  25 +-
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |  20 ++
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |  20 ++
 .../src/main/resources/META-INF/persistence.xml |   2 +
 .../commands/StackAdvisorCommandTest.java       | 212 ++++++++++++
 .../server/checks/UpgradeCheckOrderTest.java    |   3 +-
 ...AmbariConfigurationResourceProviderTest.java | 251 ++++++++++++++
 .../StackAdvisorResourceProviderTest.java       |  97 +++---
 .../server/ldap/LdapModuleFunctionalTest.java   | 149 +++++++++
 .../TestAmbariLdapConfigurationFactory.java     |  29 ++
 .../ldap/service/AmbariLdapFacadeTest.java      | 215 ++++++++++++
 ...efaultLdapAttributeDetectionServiceTest.java | 188 +++++++++++
 .../DefaultLdapConfigurationServiceTest.java    | 221 +++++++++++++
 .../detectors/GroupMemberAttrDetectorTest.java  | 107 ++++++
 .../notifications/DispatchFactoryTest.java      |   3 +-
 .../server/orm/InMemoryDefaultTestModule.java   |   2 +
 .../ambari/server/orm/JdbcPropertyTest.java     |   5 +-
 ...uthenticationProviderForDNWithSpaceTest.java |  35 +-
 .../AmbariLdapAuthenticationProviderTest.java   |   3 +-
 .../AmbariLocalUserProviderTest.java            |   3 +-
 .../authorization/LdapServerPropertiesTest.java |   5 +-
 78 files changed, 5409 insertions(+), 355 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-funtest/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-funtest/pom.xml b/ambari-funtest/pom.xml
index bb2068d..6466af3 100644
--- a/ambari-funtest/pom.xml
+++ b/ambari-funtest/pom.xml
@@ -197,73 +197,6 @@
       <artifactId>spring-ldap-core</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-server-annotations</artifactId>
-      <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>net.sf.ehcache</groupId>
-          <artifactId>ehcache-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-core-integ</artifactId>
-      <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>net.sf.ehcache</groupId>
-          <artifactId>ehcache-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-server-integ</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-jdbm</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-kerberos-codec</artifactId>
-      <exclusions>
-        <exclusion>
-          <groupId>net.sf.ehcache</groupId>
-          <artifactId>ehcache-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-core</artifactId>
-      <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>net.sf.ehcache</groupId>
-          <artifactId>ehcache-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-protocol-ldap</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>kerberos-client</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.shared</groupId>
-      <artifactId>shared-ldap</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
       <version>1.7.20</version>

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-project/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-project/pom.xml b/ambari-project/pom.xml
index 00ba1bc..f6e3bc7 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>
@@ -161,57 +162,6 @@
         <version>2.0.4.RELEASE</version>
       </dependency>
       <dependency>
-        <groupId>org.apache.directory.server</groupId>
-        <artifactId>apacheds-server-annotations</artifactId>
-        <version>2.0.0-M19</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.directory.server</groupId>
-        <artifactId>apacheds-core-integ</artifactId>
-        <version>2.0.0-M19</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.directory.server</groupId>
-        <artifactId>apacheds-server-integ</artifactId>
-        <version>2.0.0-M19</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.directory.server</groupId>
-        <artifactId>apacheds-jdbm</artifactId>
-        <version>2.0.0-M5</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.directory.server</groupId>
-        <artifactId>apacheds-kerberos-codec</artifactId>
-        <version>2.0.0-M19</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.directory.server</groupId>
-        <artifactId>apacheds-core</artifactId>
-        <version>2.0.0-M19</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.directory.server</groupId>
-        <artifactId>kerberos-client</artifactId>
-        <version>2.0.0-M19</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.directory.server</groupId>
-        <artifactId>apacheds-protocol-ldap</artifactId>
-        <version>2.0.0-M19</version>
-        <exclusions>
-          <exclusion>
-            <groupId>org.apache.directory.jdbm</groupId>
-            <artifactId>apacheds-jdbm1</artifactId>
-          </exclusion>
-        </exclusions>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.directory.shared</groupId>
-        <artifactId>shared-ldap</artifactId>
-        <version>0.9.17</version>
-      </dependency>
-      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
         <version>${slf4j.version}</version>

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index e250da7..a86acf5 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -1225,73 +1225,6 @@
       <artifactId>spring-ldap-core</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-server-annotations</artifactId>
-      <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>net.sf.ehcache</groupId>
-          <artifactId>ehcache-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-core-integ</artifactId>
-      <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>net.sf.ehcache</groupId>
-          <artifactId>ehcache-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-server-integ</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-jdbm</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-kerberos-codec</artifactId>
-      <exclusions>
-        <exclusion>
-          <groupId>net.sf.ehcache</groupId>
-          <artifactId>ehcache-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-core</artifactId>
-      <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>net.sf.ehcache</groupId>
-          <artifactId>ehcache-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>apacheds-protocol-ldap</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.server</groupId>
-      <artifactId>kerberos-client</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.directory.shared</groupId>
-      <artifactId>shared-ldap</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>
@@ -1622,6 +1555,12 @@
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-auth</artifactId>
       <version>${hadoop.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.directory.server</groupId>
+          <artifactId>apacheds-kerberos-codec</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.hadoop</groupId>
@@ -1689,6 +1628,16 @@
       <version>4.2.2</version>
     </dependency>
     <dependency>
+      <groupId>org.apache.directory.server</groupId>
+      <artifactId>apacheds-all</artifactId>
+      <version>2.0.0-M24</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.directory.server</groupId>
+      <artifactId>kerberos-client</artifactId>
+      <version>2.0.0-M24</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/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index d0d115d..f5fb6e9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -471,6 +471,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
       case RemoteCluster:
         resourceDefinition = new RemoteClusterResourceDefinition();
         break;
+      case AmbariConfiguration:
+        resourceDefinition = new SimpleResourceDefinition(Resource.Type.AmbariConfiguration, "ambariconfiguration", "ambariconfigurations");
+
+        break;
 
       default:
         throw new IllegalArgumentException("Unsupported resource type: " + type);

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/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
new file mode 100644
index 0000000..5e8094e
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.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;
+
+import java.util.Map;
+
+import org.apache.ambari.server.controller.ApiModel;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Request data model for {@link org.apache.ambari.server.api.services.AmbariConfigurationService}
+ */
+public interface AmbariConfigurationRequestSwagger extends ApiModel {
+
+  @ApiModelProperty(name = "AmbariConfiguration")
+  AmbariConfigurationRequestInfo getAmbariConfiguration();
+
+  interface AmbariConfigurationRequestInfo {
+    @ApiModelProperty
+    Long getId();
+
+    @ApiModelProperty
+    Map<String, Object> getData();
+
+    @ApiModelProperty
+    String getType();
+
+    @ApiModelProperty
+    Long getVersion();
+
+    @ApiModelProperty(name = "version_tag")
+    String getVersionTag();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java
new file mode 100644
index 0000000..c55ac1d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+import java.util.Map;
+
+import org.apache.ambari.server.controller.ApiModel;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Response data model for {@link org.apache.ambari.server.api.services.AmbariConfigurationService}
+ */
+public interface AmbariConfigurationResponseSwagger extends ApiModel {
+
+  @ApiModelProperty(name = "AmbariConfiguration")
+  AmbariConfigurationResponseInfo getAmbariConfigurationResponse();
+
+  interface AmbariConfigurationResponseInfo {
+    @ApiModelProperty
+    Long getId();
+
+    @ApiModelProperty
+    Map<String, Object> getData();
+
+    @ApiModelProperty
+    String getType();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java
new file mode 100644
index 0000000..38ae766
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java
@@ -0,0 +1,193 @@
+/*
+ * 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;
+
+import java.util.Collections;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.http.HttpStatus;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+/**
+ * Rest endpoint for managing ambari configurations. Supports CRUD operations.
+ * Ambari configurations are resources that relate to the ambari server instance even before a cluster is provisioned.
+ *
+ * Ambari configuration resources may be shared with components and services in the cluster
+ * (by recommending them as default values)
+ *
+ * Eg. LDAP configuration is stored as ambariconfiguration.
+ * The request payload has the form:
+ *
+ * <pre>
+ *      {
+ *        "AmbariConfiguration": {
+ *            "type": "ldap-configuration",
+ *            "data": [
+ *                {
+ *                 "authentication.ldap.primaryUrl": "localhost:33389"
+ *                 "authentication.ldap.secondaryUrl": "localhost:333"
+ *                 "authentication.ldap.baseDn": "dc=ambari,dc=apache,dc=org"
+ *                 // ......
+ *         ]
+ *     }
+ * </pre>
+ */
+@Path("/ambariconfigs/")
+@Api(value = "Ambari Configurations", description = "Endpoint for Ambari configuration related operations")
+public class AmbariConfigurationService extends BaseService {
+
+  private static final String AMBARI_CONFIGURATION_REQUEST_TYPE =
+    "org.apache.ambari.server.api.services.AmbariConfigurationRequestSwagger";
+
+  /**
+   * Creates an ambari configuration resource.
+   *
+   * @param body    the payload in json format
+   * @param headers http headers
+   * @param uri     request uri information
+   * @return
+   */
+  @POST
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Creates an ambari configuration resource",
+    nickname = "AmbariConfigurationService#createAmbariConfiguration")
+  @ApiImplicitParams({
+    @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
+  })
+  @ApiResponses({
+    @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION),
+    @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
+    @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+    @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS),
+    @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+    @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response createAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri) {
+    return handleRequest(headers, body, uri, Request.Type.POST, createResource(Resource.Type.AmbariConfiguration,
+      Collections.EMPTY_MAP));
+  }
+
+  @GET
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Retrieve all ambari configuration resources",
+    nickname = "AmbariConfigurationService#getAmbariConfigurations",
+    notes = "Returns all Ambari configurations.",
+    response = AmbariConfigurationResponseSwagger.class,
+    responseContainer = RESPONSE_CONTAINER_LIST)
+  @ApiImplicitParams({
+    @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION,
+      defaultValue = "AmbariConfiguration/data, AmbariConfiguration/id, AmbariConfiguration/type",
+      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+    @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION,
+      defaultValue = "AmbariConfiguration/id",
+      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+    @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+    @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+    @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+  })
+  @ApiResponses(value = {
+    @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
+  })
+  public Response getAmbariConfigurations(String body, @Context HttpHeaders headers, @Context UriInfo uri) {
+    return handleRequest(headers, body, uri, Request.Type.GET, createResource(Resource.Type.AmbariConfiguration,
+      Collections.EMPTY_MAP));
+  }
+
+  @GET
+  @Path("{configurationId}")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Retrieve the details of an ambari configuration resource",
+    nickname = "AmbariConfigurationService#getAmbariConfiguration",
+    response = AmbariConfigurationResponseSwagger.class)
+  @ApiImplicitParams({
+    @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "AmbariConfiguration/*",
+      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+  })
+  @ApiResponses(value = {
+    @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+    @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
+  })
+  public Response getAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri,
+                                         @PathParam("configurationId") String configurationId) {
+    return handleRequest(headers, body, uri, Request.Type.GET, createResource(Resource.Type.AmbariConfiguration,
+      Collections.singletonMap(Resource.Type.AmbariConfiguration, configurationId)));
+  }
+
+  @PUT
+  @Path("{configurationId}")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Updates ambari configuration resources ",
+    nickname = "AmbariConfigurationService#updateAmbariConfiguration")
+  @ApiImplicitParams({
+    @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY),
+    @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "AmbariConfiguration/*",
+      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+  })
+  @ApiResponses({
+    @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+    @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
+    @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+    @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+    @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+    @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response updateAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri,
+                                            @PathParam("configurationId") String configurationId) {
+    return handleRequest(headers, body, uri, Request.Type.PUT, createResource(Resource.Type.AmbariConfiguration,
+      Collections.singletonMap(Resource.Type.AmbariConfiguration, configurationId)));
+  }
+
+  @DELETE
+  @Path("{configurationId}")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Deletes an ambari configuration resource",
+    nickname = "AmbariConfigurationService#deleteAmbariConfiguration")
+  @ApiResponses({
+    @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+    @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+    @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+    @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response deleteAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri,
+                                            @PathParam("configurationId") String configurationId) {
+    return handleRequest(headers, body, uri, Request.Type.DELETE, createResource(Resource.Type.AmbariConfiguration,
+      Collections.singletonMap(Resource.Type.AmbariConfiguration, configurationId)));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
new file mode 100644
index 0000000..b5cc921
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
@@ -0,0 +1,87 @@
+/*
+ * 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;
+
+/**
+ * Domain POJO representing generic ambari configuration data.
+ */
+public class AmbariConfiguration {
+
+  /**
+   * The type of the configuration,  eg.: ldap-configuration
+   */
+  private String type;
+
+  /**
+   * Version tag
+   */
+  private String versionTag;
+
+  /**
+   * Version number
+   */
+  private Integer version;
+
+  /**
+   * Created timestamp
+   */
+  private long createdTs;
+
+  private Set<Map<String, Object>> data = Collections.emptySet();
+
+  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/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
new file mode 100644
index 0000000..478d4ff
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+/**
+ * Enumeration for supported operations related to LDAP configuration.
+ */
+public enum LdapConfigOperation {
+  TEST_CONNECTION("test-connection"),
+  TEST_ATTRIBUTES("test-attributes"),
+  DETECT_ATTRIBUTES("detect-attributes");
+
+  private String actionStr;
+
+  LdapConfigOperation(String actionStr) {
+    this.actionStr = actionStr;
+  }
+
+  public static LdapConfigOperation fromAction(String action) {
+    for (LdapConfigOperation val : LdapConfigOperation.values()) {
+      if (val.action().equals(action)) {
+        return val;
+      }
+    }
+    throw new IllegalStateException("Action [ " + action + " ] is not supported");
+  }
+
+  public String action() {
+    return this.actionStr;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
new file mode 100644
index 0000000..2e478c4
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+/**
+ * Request object wrapping information for LDAP configuration related request calls.
+ */
+public class LdapConfigurationRequest {
+
+  @SerializedName("AmbariConfiguration")
+  private AmbariConfiguration ambariConfiguration;
+
+  @SerializedName("RequestInfo")
+  private LdapRequestInfo requestInfo;
+
+  public LdapConfigurationRequest() {
+  }
+
+  public AmbariConfiguration getAmbariConfiguration() {
+    return ambariConfiguration;
+  }
+
+  public void setAmbariConfiguration(AmbariConfiguration 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/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
new file mode 100644
index 0000000..13f8835
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
@@ -0,0 +1,185 @@
+/*
+ * 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 java.util.Set;
+
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+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.AmbariConfigurationService;
+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.controller.internal.ResourceImpl;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationFactory;
+import org.apache.ambari.server.ldap.service.LdapFacade;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ResourceType;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Endpoint designated to LDAP specific operations.
+ */
+@StaticallyInject
+@Path("/ldapconfigs/")
+public class LdapConfigurationService extends AmbariConfigurationService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(LdapConfigurationService.class);
+
+  @Inject
+  private static LdapFacade ldapFacade;
+
+  @Inject
+  private static AmbariLdapConfigurationFactory ambariLdapConfigurationFactory;
+
+
+  @POST
+  @ApiIgnore // until documented
+  @Path("/validate")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response validateConfiguration(LdapConfigurationRequest ldapConfigurationRequest) {
+
+    // check if the user is authorized to perform the operation
+    authorize();
+
+    Set<String> groups = Sets.newHashSet();
+    Object responseEntity = null;
+
+    Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
+    try {
+
+      validateRequest(ldapConfigurationRequest);
+
+      AmbariLdapConfiguration ambariLdapConfiguration = ambariLdapConfigurationFactory.createLdapConfiguration(
+        ldapConfigurationRequest.getAmbariConfiguration().getData().iterator().next());
+
+      LdapConfigOperation action = LdapConfigOperation.fromAction(ldapConfigurationRequest.getRequestInfo().getAction());
+      switch (action) {
+
+        case TEST_CONNECTION:
+
+          LOGGER.info("Testing connection to the LDAP server ...");
+          ldapFacade.checkConnection(ambariLdapConfiguration);
+
+          break;
+        case TEST_ATTRIBUTES:
+
+          LOGGER.info("Testing LDAP attributes ....");
+          groups = ldapFacade.checkLdapAttributes(ldapConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
+          responseEntity = groups;
+
+          break;
+        case DETECT_ATTRIBUTES:
+
+          LOGGER.info("Detecting LDAP attributes ...");
+          ambariLdapConfiguration = ldapFacade.detectAttributes(ambariLdapConfiguration);
+          responseEntity = ambariLdapConfiguration;
+
+          break;
+        default:
+          LOGGER.warn("No action provided ...");
+          throw new IllegalArgumentException("No request action provided");
+      }
+
+    } catch (Exception e) {
+      result.setResultStatus(new ResultStatus(ResultStatus.STATUS.SERVER_ERROR, e));
+      responseEntity = e.getMessage();
+    }
+
+    return Response.status(result.getStatus().getStatusCode()).entity(responseEntity).build();
+  }
+
+  private void setResult(Set<String> groups, Result result) {
+    Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
+    resource.setProperty("groups", groups);
+    result.getResultTree().addChild(resource, "payload");
+  }
+
+  private void validateRequest(LdapConfigurationRequest ldapConfigurationRequest) {
+    String errMsg;
+
+    if (null == ldapConfigurationRequest) {
+      errMsg = "No ldap configuraiton request provided";
+      LOGGER.error(errMsg);
+      throw new IllegalArgumentException(errMsg);
+    }
+
+    if (null == ldapConfigurationRequest.getRequestInfo()) {
+      errMsg = String.format("No request information provided. Request: [%s]", ldapConfigurationRequest);
+      LOGGER.error(errMsg);
+      throw new IllegalArgumentException(errMsg);
+    }
+
+    if (null == ldapConfigurationRequest.getAmbariConfiguration()
+      || ldapConfigurationRequest.getAmbariConfiguration().getData().size() != 1) {
+      errMsg = String.format("No / Invalid configuration data provided. Request: [%s]", ldapConfigurationRequest);
+      LOGGER.error(errMsg);
+      throw new IllegalArgumentException(errMsg);
+    }
+  }
+
+  private void authorize() {
+    try {
+      Authentication authentication = AuthorizationHelper.getAuthentication();
+
+      if (authentication == null || !authentication.isAuthenticated()) {
+        throw new AuthorizationException("Authentication data is not available, authorization to perform the requested operation is not granted");
+      }
+
+      if (!AuthorizationHelper.isAuthorized(authentication, ResourceType.AMBARI, null, requiredAuthorizations())) {
+        throw new AuthorizationException("The authenticated user does not have the appropriate authorizations to create the requested resource(s)");
+      }
+    } catch (AuthorizationException e) {
+      LOGGER.error("Unauthorized operation.", e);
+      throw new IllegalArgumentException("User is not authorized to perform the operation", e);
+    }
+
+  }
+
+  private Set<RoleAuthorization> requiredAuthorizations() {
+    return Sets.newHashSet(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/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/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
index 3a2b488..cd26c56 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
@@ -31,6 +31,8 @@ import org.apache.ambari.server.api.services.stackadvisor.recommendations.Recomm
 import org.apache.ambari.server.state.ChangedConfigInfo;
 import org.apache.commons.lang.StringUtils;
 
+import com.google.common.base.Preconditions;
+
 /**
  * Stack advisor request.
  */
@@ -48,6 +50,7 @@ public class StackAdvisorRequest {
   private List<ChangedConfigInfo> changedConfigurations = new LinkedList<>();
   private Set<RecommendationResponse.ConfigGroup> configGroups;
   private Map<String, String> userContext = new HashMap<>();
+  private Map<String, Object> ldapConfig = new HashMap<>();
 
   public String getStackName() {
     return stackName;
@@ -93,6 +96,8 @@ public class StackAdvisorRequest {
     return configurations;
   }
 
+  public Map<String, Object> getLdapConfig() { return ldapConfig; }
+
   public List<ChangedConfigInfo> getChangedConfigurations() {
     return changedConfigurations;
   }
@@ -189,6 +194,13 @@ public class StackAdvisorRequest {
       return this;
     }
 
+    public StackAdvisorRequestBuilder withLdapConfig(Map<String, Object> ldapConfig) {
+      Preconditions.checkNotNull(ldapConfig);
+      this.instance.ldapConfig = ldapConfig;
+      return this;
+    }
+
+
     public StackAdvisorRequest build() {
       return this.instance;
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
index 356754d..2dc45de 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
@@ -84,6 +84,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
       + ",services/configurations/dependencies/StackConfigurationDependency/dependency_name"
       + ",services/configurations/dependencies/StackConfigurationDependency/dependency_type,services/configurations/StackConfigurations/type"
       + "&services/StackServices/service_name.in(%s)";
+  private static final String GET_LDAP_CONFIG_URI = "/api/v1/configurations?AmbariConfiguration/type=ldap&fields=AmbariConfiguration/*";
   private static final String SERVICES_PROPERTY = "services";
   private static final String SERVICES_COMPONENTS_PROPERTY = "components";
   private static final String CONFIG_GROUPS_PROPERTY = "config-groups";
@@ -95,6 +96,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
   private static final String CHANGED_CONFIGURATIONS_PROPERTY = "changed-configurations";
   private static final String USER_CONTEXT_PROPERTY = "user-context";
   private static final String AMBARI_SERVER_CONFIGURATIONS_PROPERTY = "ambari-server-properties";
+  protected static final String LDAP_CONFIGURATION_PROPERTY = "ldap-configuration";
 
   private File recommendationsDir;
   private String recommendationsArtifactsLifetime;
@@ -160,6 +162,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
       populateConfigurations(root, request);
       populateConfigGroups(root, request);
       populateAmbariServerInfo(root);
+      populateLdapConfiguration(root);
       data.servicesJSON = mapper.writeValueAsString(root);
     } catch (Exception e) {
       // should not happen
@@ -171,6 +174,52 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
     return data;
   }
 
+  /**
+   * Retrieves the LDAP configuration if exists and adds it to services.json
+   * @param root The JSON document that will become service.json when passed to the stack advisor engine
+   * @throws StackAdvisorException
+   * @throws IOException
+   */
+  protected void populateLdapConfiguration(ObjectNode root) throws StackAdvisorException, IOException {
+    Response response = handleRequest(null, null, new LocalUriInfo(GET_LDAP_CONFIG_URI), Request.Type.GET,
+        createConfigResource());
+
+    if (response.getStatus() != Status.OK.getStatusCode()) {
+      String message = String.format(
+          "Error occured during retrieving ldap configuration, status=%s, response=%s",
+          response.getStatus(), (String) response.getEntity());
+      LOG.warn(message);
+      throw new StackAdvisorException(message);
+    }
+
+    String ldapConfigJSON = (String) response.getEntity();
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("LDAP configuration: {}", ldapConfigJSON);
+    }
+
+    JsonNode ldapConfigRoot = mapper.readTree(ldapConfigJSON);
+    ArrayNode ldapConfigs = ((ArrayNode)ldapConfigRoot.get("items"));
+    int numConfigs = ldapConfigs.size();
+    // Zero or one config may exist
+    switch (numConfigs) {
+      case 0:
+        LOG.debug("No LDAP config is stored in the DB");
+        break;
+      case 1:
+        ArrayNode ldapConfigData = (ArrayNode)ldapConfigs.get(0).get("AmbariConfiguration").get("data");
+        if (ldapConfigData.size() == 0) {
+          throw new StackAdvisorException("No configuration data for LDAP configuration.");
+        }
+        if (ldapConfigData.size() > 1) {
+          throw new StackAdvisorException("Ambigous configuration data for LDAP configuration.");
+        }
+        root.put(LDAP_CONFIGURATION_PROPERTY, ldapConfigData.get(0));
+        break;
+      default:
+        throw new StackAdvisorException(String.format("Multiple (%s) LDAP configs are found in the DB.", numConfigs));
+    }
+  }
+
   protected void populateAmbariServerInfo(ObjectNode root) throws StackAdvisorException {
     Map<String, String> serverProperties = metaInfo.getAmbariServerProperties();
 
@@ -437,6 +486,11 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
     return createResource(Resource.Type.Host, mapIds);
   }
 
+  protected ResourceInstance createConfigResource() {
+    return createResource(Resource.Type.AmbariConfiguration, new HashMap<>());
+  }
+
+
   private ResourceInstance createStackVersionResource(String stackName, String stackVersion) {
     Map<Resource.Type, String> mapIds = new HashMap<>();
     mapIds.put(Resource.Type.Stack, stackName);

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/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/6b7a7a70/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 dc97871..1425e1b 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
@@ -63,6 +63,7 @@ import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.configuration.Configuration.ConnectionPoolType;
 import org.apache.ambari.server.configuration.Configuration.DatabaseType;
 import org.apache.ambari.server.controller.internal.AlertTargetResourceProvider;
+import org.apache.ambari.server.controller.internal.AmbariConfigurationResourceProvider;
 import org.apache.ambari.server.controller.internal.ClusterStackVersionResourceProvider;
 import org.apache.ambari.server.controller.internal.ComponentResourceProvider;
 import org.apache.ambari.server.controller.internal.CredentialResourceProvider;
@@ -470,6 +471,7 @@ public class ControllerModule extends AbstractModule {
         .implement(ResourceProvider.class, Names.named("credential"), CredentialResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("kerberosDescriptor"), KerberosDescriptorResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("upgrade"), UpgradeResourceProvider.class)
+        .implement(ResourceProvider.class, Names.named("ambariConfiguration"), AmbariConfigurationResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("clusterStackVersion"), ClusterStackVersionResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("alertTarget"), AlertTargetResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("viewInstance"), ViewInstanceResourceProvider.class)
@@ -508,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/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
index a198775..711ae10 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
@@ -22,6 +22,8 @@ package org.apache.ambari.server.controller;
 import java.util.Map;
 import java.util.Set;
 
+import javax.inject.Named;
+
 import org.apache.ambari.server.controller.internal.AlertTargetResourceProvider;
 import org.apache.ambari.server.controller.internal.ClusterStackVersionResourceProvider;
 import org.apache.ambari.server.controller.internal.UpgradeResourceProvider;
@@ -30,18 +32,15 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.Resource.Type;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
 
-import com.google.inject.name.Named;
 
 public interface ResourceProviderFactory {
   @Named("host")
-  ResourceProvider getHostResourceProvider(Set<String> propertyIds,
-      Map<Type, String> keyPropertyIds,
-      AmbariManagementController managementController);
+  ResourceProvider getHostResourceProvider(Set<String> propertyIds, Map<Type, String> keyPropertyIds,
+                                           AmbariManagementController managementController);
 
   @Named("hostComponent")
-  ResourceProvider getHostComponentResourceProvider(Set<String> propertyIds,
-      Map<Type, String> keyPropertyIds,
-      AmbariManagementController managementController);
+  ResourceProvider getHostComponentResourceProvider(Set<String> propertyIds, Map<Type, String> keyPropertyIds,
+                                                    AmbariManagementController managementController);
 
   @Named("service")
   ResourceProvider getServiceResourceProvider(AmbariManagementController managementController);
@@ -50,9 +49,8 @@ public interface ResourceProviderFactory {
   ResourceProvider getComponentResourceProvider(AmbariManagementController managementController);
 
   @Named("member")
-  ResourceProvider getMemberResourceProvider(Set<String> propertyIds,
-      Map<Type, String> keyPropertyIds,
-      AmbariManagementController managementController);
+  ResourceProvider getMemberResourceProvider(Set<String> propertyIds, Map<Type, String> keyPropertyIds,
+                                             AmbariManagementController managementController);
 
   @Named("hostKerberosIdentity")
   ResourceProvider getHostKerberosIdentityResourceProvider(AmbariManagementController managementController);
@@ -64,13 +62,15 @@ public interface ResourceProviderFactory {
   ResourceProvider getRepositoryVersionResourceProvider();
 
   @Named("kerberosDescriptor")
-  ResourceProvider getKerberosDescriptorResourceProvider(AmbariManagementController managementController,
-                                                         Set<String> propertyIds,
+  ResourceProvider getKerberosDescriptorResourceProvider(AmbariManagementController managementController, Set<String> propertyIds,
                                                          Map<Resource.Type, String> keyPropertyIds);
 
   @Named("upgrade")
   UpgradeResourceProvider getUpgradeResourceProvider(AmbariManagementController managementController);
 
+  @Named("ambariConfiguration")
+  ResourceProvider getAmbariConfigurationResourceProvider();
+
   @Named("clusterStackVersion")
   ClusterStackVersionResourceProvider getClusterStackVersionResourceProvider(AmbariManagementController managementController);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index a98ad46..1dc0841 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -254,6 +254,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
         return new ClusterKerberosDescriptorResourceProvider(managementController);
       case LoggingQuery:
         return new LoggingResourceProvider(propertyIds, keyPropertyIds, managementController);
+      case AmbariConfiguration:
+        return resourceProviderFactory.getAmbariConfigurationResourceProvider();
       case AlertTarget:
         return resourceProviderFactory.getAlertTargetResourceProvider();
       case ViewInstance:

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
index 1cd2d10..1501a01 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
@@ -224,7 +224,7 @@ public abstract class AbstractProviderModule implements ProviderModule,
    * are going to work unless refactoring is complete.
    */
   @Inject
-  AmbariManagementController managementController;
+  protected AmbariManagementController managementController;
 
   @Inject
   TimelineMetricCacheProvider metricCacheProvider;

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java
new file mode 100644
index 0000000..4f4cc70
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java
@@ -0,0 +1,328 @@
+/*
+ * 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.controller.internal;
+
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PredicateHelper;
+import org.apache.ambari.server.events.AmbariEvent;
+import org.apache.ambari.server.events.AmbariLdapConfigChangedEvent;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
+import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
+import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity;
+import org.apache.ambari.server.orm.entities.ConfigurationBaseEntity;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Sets;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.inject.assistedinject.AssistedInject;
+
+/**
+ * Resource provider for AmbariConfiguration resources.
+ */
+public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResourceProvider {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariConfigurationResourceProvider.class);
+  private static final String DEFAULT_VERSION_TAG = "Default version";
+  private static final Integer DEFAULT_VERSION = 1;
+
+  /**
+   * Resource property id constants.
+   */
+  public enum ResourcePropertyId {
+
+    ID("AmbariConfiguration/id"),
+    TYPE("AmbariConfiguration/type"),
+    VERSION("AmbariConfiguration/version"),
+    VERSION_TAG("AmbariConfiguration/version_tag"),
+    DATA("AmbariConfiguration/data");
+
+    private String propertyId;
+
+    ResourcePropertyId(String propertyId) {
+      this.propertyId = propertyId;
+    }
+
+    String getPropertyId() {
+      return this.propertyId;
+    }
+
+    public static ResourcePropertyId fromString(String propertyIdStr) {
+      ResourcePropertyId propertyIdFromStr = null;
+
+      for (ResourcePropertyId id : ResourcePropertyId.values()) {
+        if (id.getPropertyId().equals(propertyIdStr)) {
+          propertyIdFromStr = id;
+          break;
+        }
+      }
+
+      if (propertyIdFromStr == null) {
+        throw new IllegalArgumentException("Unsupported property type: " + propertyIdStr);
+      }
+
+      return propertyIdFromStr;
+
+    }
+  }
+
+  private static Set<String> PROPERTIES = Sets.newHashSet(
+    ResourcePropertyId.ID.getPropertyId(),
+    ResourcePropertyId.TYPE.getPropertyId(),
+    ResourcePropertyId.VERSION.getPropertyId(),
+    ResourcePropertyId.VERSION_TAG.getPropertyId(),
+    ResourcePropertyId.DATA.getPropertyId());
+
+  private static Map<Resource.Type, String> PK_PROPERTY_MAP = Collections.unmodifiableMap(
+    new HashMap<Resource.Type, String>() {{
+      put(Resource.Type.AmbariConfiguration, ResourcePropertyId.ID.getPropertyId());
+    }}
+  );
+
+
+  @Inject
+  private AmbariConfigurationDAO ambariConfigurationDAO;
+
+  @Inject
+  private AmbariEventPublisher publisher;
+
+
+  private Gson gson;
+
+  @AssistedInject
+  public AmbariConfigurationResourceProvider() {
+    super(PROPERTIES, PK_PROPERTY_MAP);
+    setRequiredCreateAuthorizations(EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION));
+    setRequiredDeleteAuthorizations(EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION));
+
+    gson = new GsonBuilder().create();
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return Sets.newHashSet(ResourcePropertyId.ID.getPropertyId());
+  }
+
+  @Override
+  public RequestStatus createResourcesAuthorized(Request request) throws SystemException, UnsupportedPropertyException,
+    ResourceAlreadyExistsException, NoSuchParentResourceException {
+
+    LOGGER.info("Creating new ambari configuration resource ...");
+    AmbariConfigurationEntity ambariConfigurationEntity = null;
+    try {
+      ambariConfigurationEntity = getEntityFromRequest(request);
+    } catch (AmbariException e) {
+      throw new NoSuchParentResourceException(e.getMessage());
+    }
+
+    LOGGER.info("Persisting new ambari configuration: {} ", ambariConfigurationEntity);
+
+    try {
+      ambariConfigurationDAO.create(ambariConfigurationEntity);
+    } catch (Exception e) {
+      LOGGER.error("Failed to create resource", e);
+      throw new ResourceAlreadyExistsException(e.getMessage());
+    }
+
+    // todo filter by configuration type
+    // notify subscribers about the configuration changes
+    publisher.publish(new AmbariLdapConfigChangedEvent(AmbariEvent.AmbariEventType.LDAP_CONFIG_CHANGED,
+      ambariConfigurationEntity.getId()));
+
+    return getRequestStatus(null);
+  }
+
+
+  @Override
+  protected Set<Resource> getResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
+    UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    Set<Resource> resources = Sets.newHashSet();
+
+    // retrieves allconfigurations, filtering is done at a higher level
+    List<AmbariConfigurationEntity> ambariConfigurationEntities = ambariConfigurationDAO.findAll();
+    for (AmbariConfigurationEntity ambariConfigurationEntity : ambariConfigurationEntities) {
+      try {
+        resources.add(toResource(ambariConfigurationEntity, getPropertyIds()));
+      } catch (AmbariException e) {
+        LOGGER.error("Error while retrieving ambari configuration", e);
+      }
+    }
+    return resources;
+  }
+
+  @Override
+  protected RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
+    UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+    Long idFromRequest = Long.valueOf((String) PredicateHelper.getProperties(predicate).get(ResourcePropertyId.ID.getPropertyId()));
+
+    if (null == idFromRequest) {
+      LOGGER.debug("No resource id provided in the request");
+    } else {
+      LOGGER.debug("Deleting amari configuration with id: {}", idFromRequest);
+      try {
+        ambariConfigurationDAO.removeByPK(idFromRequest);
+      } catch (IllegalStateException e) {
+        throw new NoSuchResourceException(e.getMessage());
+      }
+
+    }
+
+    // notify subscribers about the configuration changes
+    publisher.publish(new AmbariLdapConfigChangedEvent(AmbariEvent.AmbariEventType.LDAP_CONFIG_CHANGED, idFromRequest));
+
+
+    return getRequestStatus(null);
+
+  }
+
+  @Override
+  protected RequestStatus updateResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
+    UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    Long idFromRequest = Long.valueOf((String) PredicateHelper.getProperties(predicate).get(ResourcePropertyId.ID.getPropertyId()));
+
+    AmbariConfigurationEntity persistedEntity = ambariConfigurationDAO.findByPK(idFromRequest);
+    if (persistedEntity == null) {
+      String errorMsg = String.format("Entity with primary key [ %s ] not found in the database.", idFromRequest);
+      LOGGER.error(errorMsg);
+      throw new NoSuchResourceException(errorMsg);
+    }
+
+    try {
+
+      AmbariConfigurationEntity entityFromRequest = getEntityFromRequest(request);
+      persistedEntity.getConfigurationBaseEntity().setVersionTag(entityFromRequest.getConfigurationBaseEntity().getVersionTag());
+      persistedEntity.getConfigurationBaseEntity().setVersion(entityFromRequest.getConfigurationBaseEntity().getVersion());
+      persistedEntity.getConfigurationBaseEntity().setType(entityFromRequest.getConfigurationBaseEntity().getType());
+      persistedEntity.getConfigurationBaseEntity().setConfigurationData(entityFromRequest.getConfigurationBaseEntity().getConfigurationData());
+      persistedEntity.getConfigurationBaseEntity().setConfigurationAttributes(entityFromRequest.getConfigurationBaseEntity().getConfigurationAttributes());
+
+
+      ambariConfigurationDAO.update(persistedEntity);
+    } catch (AmbariException e) {
+      throw new NoSuchParentResourceException(e.getMessage());
+    }
+
+    publisher.publish(new AmbariLdapConfigChangedEvent(AmbariEvent.AmbariEventType.LDAP_CONFIG_CHANGED,
+      persistedEntity.getId()));
+
+
+    return getRequestStatus(null);
+
+  }
+
+  private Resource toResource(AmbariConfigurationEntity entity, Set<String> requestedIds) throws AmbariException {
+
+    if (null == entity) {
+      throw new IllegalArgumentException("Null entity can't be transformed into a resource");
+    }
+
+    if (null == entity.getConfigurationBaseEntity()) {
+      throw new IllegalArgumentException("Invalid configuration entity can't be transformed into a resource");
+    }
+    Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
+    Set<Map<String, String>> configurationSet = gson.fromJson(entity.getConfigurationBaseEntity().getConfigurationData(), Set.class);
+
+    setResourceProperty(resource, ResourcePropertyId.ID.getPropertyId(), entity.getId(), requestedIds);
+    setResourceProperty(resource, ResourcePropertyId.TYPE.getPropertyId(), entity.getConfigurationBaseEntity().getType(), requestedIds);
+    setResourceProperty(resource, ResourcePropertyId.DATA.getPropertyId(), configurationSet, requestedIds);
+    setResourceProperty(resource, ResourcePropertyId.VERSION.getPropertyId(), entity.getConfigurationBaseEntity().getVersion(), requestedIds);
+    setResourceProperty(resource, ResourcePropertyId.VERSION_TAG.getPropertyId(), entity.getConfigurationBaseEntity().getVersionTag(), requestedIds);
+
+    return resource;
+  }
+
+  private AmbariConfigurationEntity getEntityFromRequest(Request request) throws AmbariException {
+
+    AmbariConfigurationEntity ambariConfigurationEntity = new AmbariConfigurationEntity();
+    ambariConfigurationEntity.setConfigurationBaseEntity(new ConfigurationBaseEntity());
+
+    // set of resource properties (eache entry in the set belongs to a different resource)
+    Set<Map<String, Object>> resourcePropertiesSet = request.getProperties();
+
+    if (resourcePropertiesSet.size() != 1) {
+      throw new AmbariException("There must be only one resource specified in the request");
+    }
+
+    // the configuration type must be set
+    if (getValueFromResourceProperties(ResourcePropertyId.TYPE, resourcePropertiesSet.iterator().next()) == null) {
+      throw new AmbariException("The configuration type must be set");
+    }
+
+
+    for (ResourcePropertyId resourcePropertyId : ResourcePropertyId.values()) {
+      Object requestValue = getValueFromResourceProperties(resourcePropertyId, resourcePropertiesSet.iterator().next());
+
+      switch (resourcePropertyId) {
+        case DATA:
+          if (requestValue == null) {
+            throw new IllegalArgumentException("No configuration data is provided in the request");
+          }
+          ambariConfigurationEntity.getConfigurationBaseEntity().setConfigurationData(gson.toJson(requestValue));
+          break;
+        case TYPE:
+          ambariConfigurationEntity.getConfigurationBaseEntity().setType((String) requestValue);
+          break;
+        case VERSION:
+          Integer version = (requestValue == null) ? DEFAULT_VERSION : Integer.valueOf((String) requestValue);
+          ambariConfigurationEntity.getConfigurationBaseEntity().setVersion((version));
+          break;
+        case VERSION_TAG:
+          String versionTag = requestValue == null ? DEFAULT_VERSION_TAG : (String) requestValue;
+          ambariConfigurationEntity.getConfigurationBaseEntity().setVersionTag(versionTag);
+          break;
+        default:
+          LOGGER.debug("Ignored property in the request: {}", resourcePropertyId);
+          break;
+      }
+    }
+    ambariConfigurationEntity.getConfigurationBaseEntity().setCreateTimestamp(Calendar.getInstance().getTimeInMillis());
+    return ambariConfigurationEntity;
+
+  }
+
+  private Object getValueFromResourceProperties(ResourcePropertyId resourcePropertyIdEnum, Map<String, Object> resourceProperties) {
+    LOGGER.debug("Locating resource property [{}] in the resource properties map ...", resourcePropertyIdEnum);
+    Object requestValue = null;
+
+    if (resourceProperties.containsKey(resourcePropertyIdEnum.getPropertyId())) {
+      requestValue = resourceProperties.get(resourcePropertyIdEnum.getPropertyId());
+      LOGGER.debug("Found resource property {} in the resource properties map, value: {}", resourcePropertyIdEnum, requestValue);
+    }
+    return requestValue;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
index 43779a3..c3758b3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
@@ -21,20 +21,18 @@ package org.apache.ambari.server.controller.internal;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.ambari.server.controller.AmbariManagementController;
-import org.apache.ambari.server.controller.AmbariServer;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
-
-import com.google.inject.Inject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The default provider module implementation.
  */
 public class DefaultProviderModule extends AbstractProviderModule {
-  @Inject
-  private AmbariManagementController managementController;
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultProviderModule.class);
 
   // ----- Constructors ------------------------------------------------------
 
@@ -42,9 +40,7 @@ public class DefaultProviderModule extends AbstractProviderModule {
    * Create a default provider module.
    */
   public DefaultProviderModule() {
-    if (managementController == null) {
-      managementController = AmbariServer.getController();
-    }
+    super();
   }
 
 
@@ -52,8 +48,10 @@ public class DefaultProviderModule extends AbstractProviderModule {
 
   @Override
   protected ResourceProvider createResourceProvider(Resource.Type type) {
-    Set<String>               propertyIds    = PropertyHelper.getPropertyIds(type);
-    Map<Resource.Type,String> keyPropertyIds = PropertyHelper.getKeyPropertyIds(type);
+
+    LOGGER.debug("Creating resource provider for the type: {}", type);
+    Set<String> propertyIds = PropertyHelper.getPropertyIds(type);
+    Map<Resource.Type, String> keyPropertyIds = PropertyHelper.getKeyPropertyIds(type);
 
     switch (type.getInternalType()) {
       case Workflow:
@@ -118,10 +116,10 @@ public class DefaultProviderModule extends AbstractProviderModule {
         return new ArtifactResourceProvider(managementController);
       case RemoteCluster:
         return new RemoteClusterResourceProvider();
-
       default:
+        LOGGER.debug("Delegating creation of resource provider for: {} to the AbstractControllerResourceProvider", type.getInternalType());
         return AbstractControllerResourceProvider.getResourceProvider(type, propertyIds,
-            keyPropertyIds, managementController);
+          keyPropertyIds, managementController);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index 362b4e6..7835373 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -160,7 +160,8 @@ public interface Resource {
     VersionDefinition,
     ClusterKerberosDescriptor,
     LoggingQuery,
-    RemoteCluster;
+    RemoteCluster,
+    AmbariConfiguration;
 
     /**
      * Get the {@link Type} that corresponds to this InternalType.
@@ -282,6 +283,8 @@ public interface Resource {
     public static final Type ClusterKerberosDescriptor = InternalType.ClusterKerberosDescriptor.getType();
     public static final Type LoggingQuery = InternalType.LoggingQuery.getType();
     public static final Type RemoteCluster = InternalType.RemoteCluster.getType();
+    public static final Type AmbariConfiguration = InternalType.AmbariConfiguration.getType();
+
 
     /**
      * The type name.

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
index 9a5ee79..0f9ff52 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
@@ -140,7 +140,13 @@ public abstract class AmbariEvent {
     /**
      * Local user has been created.
      */
-    USER_CREATED;
+    USER_CREATED,
+
+    /**
+     * LDAP config changed event;
+     */
+    LDAP_CONFIG_CHANGED;
+
   }
 
   /**
@@ -151,8 +157,7 @@ public abstract class AmbariEvent {
   /**
    * Constructor.
    *
-   * @param eventType
-   *          the type of event (not {@code null}).
+   * @param eventType the type of event (not {@code null}).
    */
   public AmbariEvent(AmbariEventType eventType) {
     m_eventType = eventType;

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b7a7a70/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.java
new file mode 100644
index 0000000..48799d7
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariLdapConfigChangedEvent.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.events;
+
+/**
+ * Event signaling the creation or changing of an LDAP configuration entry.
+ */
+public class AmbariLdapConfigChangedEvent extends AmbariEvent {
+
+  private Long configurationId;
+
+  /**
+   * Constructor.
+   *
+   * @param eventType the type of event (not {@code null}).
+   */
+  public AmbariLdapConfigChangedEvent(AmbariEventType eventType, Long configurationId) {
+    super(eventType);
+    this.configurationId = configurationId;
+  }
+
+  public Long getConfigurationId() {
+    return configurationId;
+  }
+}