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/80f59d18 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/80f59d18 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/80f59d18 Branch: refs/heads/feature-branch-AMBARI-21307 Commit: 80f59d1864187691e665c6f6b269fa512aa185bf Parents: aafffd9 Author: lpuskas <lpus...@apache.org> Authored: Tue Jul 18 17:48:07 2017 +0200 Committer: lpuskas <lpus...@apache.org> Committed: Tue Aug 29 15:05:28 2017 +0200 ---------------------------------------------------------------------- ambari-project/pom.xml | 1 + ambari-server/pom.xml | 7 +- .../AmbariConfigurationRequestSwagger.java | 1 - .../services/ldap/AmbariConfigurationDTO.java | 67 +++++++ .../ldap/LdapCheckConfigurationRequest.java | 47 +++++ .../api/services/ldap/LdapOperationRequest.java | 18 ++ .../api/services/ldap/LdapRequestInfo.java | 61 +++++++ .../api/services/ldap/LdapRestService.java | 132 ++++++++++++++ .../ambari/server/controller/AmbariServer.java | 3 +- .../server/controller/ControllerModule.java | 1 + .../server/ldap/AmbariLdapConfiguration.java | 129 ++++++++++++++ .../server/ldap/LdapConfigurationFactory.java | 21 +++ .../ldap/LdapConfigurationValidatorService.java | 52 ++++++ .../apache/ambari/server/ldap/LdapModule.java | 37 ++++ .../ldap/service/AmbariLdapException.java | 33 ++++ .../server/ldap/service/AmbariLdapFacade.java | 107 +++++++++++ .../ambari/server/ldap/service/LdapFacade.java | 52 ++++++ .../server/ldap/service/LdapSearchService.java | 18 ++ .../ad/AdLdapConfigurationValidatorService.java | 177 +++++++++++++++++++ .../service/ad/LdapConfigurationConverter.java | 50 ++++++ .../api/services/ldap/LDAPServiceTest.java | 85 +++++++++ ...AdLdapConfigurationValidatorServiceTest.java | 129 ++++++++++++++ 22 files changed, 1224 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/80f59d18/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/80f59d18/ambari-server/pom.xml ---------------------------------------------------------------------- diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml index 29a820a..c0f30be 100644 --- a/ambari-server/pom.xml +++ b/ambari-server/pom.xml @@ -1287,7 +1287,6 @@ <dependency> <groupId>org.apache.directory.shared</groupId> <artifactId>shared-ldap</artifactId> - <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> @@ -1686,8 +1685,12 @@ <artifactId>jna</artifactId> <version>4.2.2</version> </dependency> + <dependency> + <groupId>org.apache.directory.api</groupId> + <artifactId>api-all</artifactId> + <version>${ldap-api.version}</version> + </dependency> </dependencies> - <pluginRepositories> <pluginRepository> <id>oss.sonatype.org</id> http://git-wip-us.apache.org/repos/asf/ambari/blob/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java index edabcdb..bf790a7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java @@ -504,6 +504,7 @@ public class ControllerModule extends AbstractModule { install(new FactoryModuleBuilder().implement(CollectionPersisterService.class, CsvFilePersisterService.class).build(CollectionPersisterServiceFactory.class)); install(new FactoryModuleBuilder().build(ConfigureClusterTaskFactory.class)); + } /** http://git-wip-us.apache.org/repos/asf/ambari/blob/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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/80f59d18/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