AMBARI-21307 renamed package, minor corrections. Changed endpoint name
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/6c3dcc78 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/6c3dcc78 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/6c3dcc78 Branch: refs/heads/feature-branch-AMBARI-21307 Commit: 6c3dcc78032680fe5999fae0f727fb659822dfde Parents: 1d75b54 Author: lpuskas <lpus...@apache.org> Authored: Mon Aug 14 13:21:07 2017 +0200 Committer: lpuskas <lpus...@apache.org> Committed: Thu Oct 19 14:41:58 2017 +0200 ---------------------------------------------------------------------- .../services/AmbariConfigurationService.java | 2 +- .../api/services/ldap/LdapRestService.java | 15 +- .../server/ldap/AmbariLdapConfiguration.java | 5 +- .../apache/ambari/server/ldap/LdapModule.java | 4 +- ...efaultLdapConfigurationValidatorService.java | 243 ------------------- .../ad/DefaultLdapConnectionService.java | 63 ----- ...efaultLdapConfigurationValidatorService.java | 243 +++++++++++++++++++ .../ads/DefaultLdapConnectionService.java | 63 +++++ ...ltLdapConfigurationValidatorServiceTest.java | 113 --------- ...ltLdapConfigurationValidatorServiceTest.java | 113 +++++++++ 10 files changed, 435 insertions(+), 429 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/6c3dcc78/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 index 927e518..492509f 100644 --- 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 @@ -63,7 +63,7 @@ import io.swagger.annotations.ApiResponses; * } * </pre> */ -@Path("/configurations/") +@Path("/ambariconfigs/") @Api(value = "Ambari Configurations", description = "Endpoint for Ambari configuration related operations") public class AmbariConfigurationService extends BaseService { http://git-wip-us.apache.org/repos/asf/ambari/blob/6c3dcc78/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 index 8578204..4e654dc 100644 --- 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 @@ -34,6 +34,7 @@ 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; @@ -70,8 +71,9 @@ public class LdapRestService extends BaseService { @POST @ApiIgnore // until documented - @Path("/action") // todo this needs to be moved under the resource + @Path("/validate") // todo this needs to be moved under the resource @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) public Response validateConfiguration(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) { Set<String> groups = Sets.newHashSet(); @@ -95,10 +97,7 @@ public class LdapRestService extends BaseService { LOGGER.info("Testing LDAP attributes ...."); groups = ldapFacade.checkLdapAttibutes(ldapCheckConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration); - // todo factor out the resource creation, design better the structure in the response - Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration); - resource.setProperty("groups", groups); - result.getResultTree().addChild(resource, "payload"); + setResult(groups, result); break; case "detect-attributes": @@ -119,6 +118,12 @@ public class LdapRestService extends BaseService { return Response.status(result.getStatus().getStatusCode()).entity(getResultSerializer().serialize(result)).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(LdapCheckConfigurationRequest ldapCheckConfigurationRequest) { String errMsg; http://git-wip-us.apache.org/repos/asf/ambari/blob/6c3dcc78/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 index 8ab587b..b1cbced 100644 --- 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 @@ -37,11 +37,12 @@ public class AmbariLdapConfiguration { 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"), + LDAP_TRUSTSTORE_TYPE("ambari.ldap.truststore.type"), + LDAP_TRUSTSTORE_PATH("ambari.ldap.truststore.path"), + BASE_DN("ambari.ldap.bind.dn"), BIND_ANONIMOUSLY("ambari.ldap.bindanonymously"), MANAGER_DN("ambari.ldap.managerdn"), http://git-wip-us.apache.org/repos/asf/ambari/blob/6c3dcc78/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 index 1b49159..a4ad2ee 100644 --- 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 @@ -18,8 +18,8 @@ package org.apache.ambari.server.ldap; import org.apache.ambari.server.ldap.service.AmbariLdapFacade; import org.apache.ambari.server.ldap.service.LdapConnectionService; import org.apache.ambari.server.ldap.service.LdapFacade; -import org.apache.ambari.server.ldap.service.ad.DefaultLdapConfigurationValidatorService; -import org.apache.ambari.server.ldap.service.ad.DefaultLdapConnectionService; +import org.apache.ambari.server.ldap.service.ads.DefaultLdapConfigurationValidatorService; +import org.apache.ambari.server.ldap.service.ads.DefaultLdapConnectionService; import com.google.inject.AbstractModule; import com.google.inject.assistedinject.FactoryModuleBuilder; http://git-wip-us.apache.org/repos/asf/ambari/blob/6c3dcc78/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java deleted file mode 100644 index a8503ca..0000000 --- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorService.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * 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 java.util.Set; - -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.ambari.server.ldap.service.LdapConnectionService; -import org.apache.directory.api.ldap.codec.decorators.SearchResultEntryDecorator; -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.exception.LdapException; -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.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.search.FilterBuilder; -import org.apache.directory.shared.ldap.constants.SchemaConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - -/** - * Implementation of the validation logic using the Apache Directory API. - */ -@Singleton -public class DefaultLdapConfigurationValidatorService implements LdapConfigurationValidatorService { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class); - - @Inject - private LdapConnectionService ldapConnectionService; - - /** - * Facilitating the instantiation - */ - @Inject - public DefaultLdapConfigurationValidatorService() { - } - - @Override - public void checkConnection(LdapConnection ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException { - try { - bind(ambariLdapConfiguration, ldapConnection); - } catch (LdapException e) { - LOGGER.error("Could not connect to the LDAP server", e); - 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 testUserName the test username - * @param testPassword the test password - * @param ambariLdapConfiguration configuration instance holding ldap configuration details - * @return the DN of the test user - * @throws AmbariException if the attributes are not valid or any errors occurs - */ - @Override - public String checkUserAttributes(LdapConnection ldapConnection, String testUserName, String testPassword, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException { - SearchCursor searchCursor = null; - String userDn = null; - try { - LOGGER.info("Checking user attributes for user {} r ...", testUserName); - - // bind anonimously or with manager data - bind(ambariLdapConfiguration, ldapConnection); - - // 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(), testUserName)) - .toString(); - - LOGGER.info("Searching for the user: {} using the search filter: {}", testUserName, filter); - EntryCursor entryCursor = ldapConnection.search(new Dn(ambariLdapConfiguration.userSearchBase()), filter, SearchScope.SUBTREE); - - // collecting search result entries - List<Entry> users = Lists.newArrayList(); - for (Entry entry : entryCursor) { - users.add(entry); - userDn = entry.getDn().getNormName(); - } - - // 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("User attributes validation failed.", e); - throw new AmbariLdapException(e.getMessage(), e); - - } finally { - closeResources(ldapConnection, searchCursor); - } - return userDn; - } - - - @Override - public Set<String> checkGroupAttributes(LdapConnection ldapConnection, String userDn, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException { - SearchCursor searchCursor = null; - Set<Response> groupResponses = Sets.newHashSet(); - - try { - LOGGER.info("Checking group attributes for user dn {} ...", userDn); - - bind(ambariLdapConfiguration, ldapConnection); - - // set up a filter based on the provided attributes - String filter = FilterBuilder.and( - FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.groupObjectClass()), - FilterBuilder.equal(ambariLdapConfiguration.groupMemberAttribute(), userDn) - ).toString(); - - LOGGER.info("Searching for the groups the user dn: {} is member of using the search filter: {}", userDn, filter); - - // assemble a search request - SearchRequest searchRequest = new SearchRequestImpl(); - searchRequest.setFilter(filter); - searchRequest.setBase(new Dn(ambariLdapConfiguration.groupSearchBase())); - searchRequest.setScope(SearchScope.SUBTREE); - searchRequest.addAttributes(ambariLdapConfiguration.groupMemberAttribute(), ambariLdapConfiguration.groupNameAttribute()); - - // perform the search - searchCursor = ldapConnection.search(searchRequest); - - for (Response response : searchCursor) { - groupResponses.add(response); - } - - } catch (Exception e) { - - LOGGER.error("User attributes validation failed.", e); - throw new AmbariLdapException(e.getMessage(), e); - - } finally { - closeResources(ldapConnection, searchCursor); - } - - return processGroupResults(groupResponses, ambariLdapConfiguration); - } - - /** - * Binds to the LDAP server (anonimously or wit manager credentials) - * - * @param ambariLdapConfiguration configuration instance - * @param connection connection instance - * @throws LdapException if the bind operation fails - */ - private void bind(AmbariLdapConfiguration ambariLdapConfiguration, LdapConnection connection) throws LdapException { - LOGGER.info("Connecting to LDAP ...."); - 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"); - } - LOGGER.info("Connected to LDAP."); - } - - - /** - * Extracts meaningful values from the search result. - * - * @param groupResponses the result entries returned by the search - * @param ambariLdapConfiguration holds the keys of the meaningful attributes - * @return a set with the group names the test user belongs to - */ - private Set<String> processGroupResults(Set<Response> groupResponses, AmbariLdapConfiguration ambariLdapConfiguration) { - Set<String> groupStrSet = Sets.newHashSet(); - for (Response response : groupResponses) { - Entry entry = ((SearchResultEntryDecorator) response).getEntry(); - groupStrSet.add(entry.get(ambariLdapConfiguration.groupNameAttribute()).get().getString()); - } - - LOGGER.debug("Extracted group names from group search responses: {}", groupStrSet); - return groupStrSet; - } - - private void closeResources(LdapConnection connection, SearchCursor searchCursor) { - LOGGER.debug("Housekeeping: closing the connection and the search cursor ..."); - - if (null != searchCursor) { - // this method is idempotent - searchCursor.close(); - } - - if (null != connection) { - try { - connection.close(); - } catch (IOException e) { - LOGGER.error("Exception occurred while closing the connection", e); - } - } - } - -} - - - http://git-wip-us.apache.org/repos/asf/ambari/blob/6c3dcc78/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java deleted file mode 100644 index 25dc1f2..0000000 --- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConnectionService.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.ldap.service.ad; - -import javax.inject.Singleton; - -import org.apache.ambari.server.ldap.AmbariLdapConfiguration; -import org.apache.ambari.server.ldap.service.LdapConnectionService; -import org.apache.directory.ldap.client.api.LdapConnectionConfig; -import org.apache.directory.ldap.client.api.LdapNetworkConnection; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Singleton -public class DefaultLdapConnectionService implements LdapConnectionService { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConnectionService.class); - - @Override - public LdapNetworkConnection createLdapConnection(AmbariLdapConfiguration ambariLdapConfiguration) { - LOGGER.debug("Creating ldap connection instance from: {}", ambariLdapConfiguration); - return new LdapNetworkConnection(getLdapConnectionConfig(ambariLdapConfiguration)); - } - - private 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/6c3dcc78/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java new file mode 100644 index 0000000..040983a --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorService.java @@ -0,0 +1,243 @@ +/* + * 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.ads; + +import java.io.IOException; +import java.util.List; +import java.util.Set; + +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.ambari.server.ldap.service.LdapConnectionService; +import org.apache.directory.api.ldap.codec.decorators.SearchResultEntryDecorator; +import org.apache.directory.api.ldap.model.constants.SchemaConstants; +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.exception.LdapException; +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.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.search.FilterBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +/** + * Implementation of the validation logic using the Apache Directory API. + */ +@Singleton +public class DefaultLdapConfigurationValidatorService implements LdapConfigurationValidatorService { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class); + + @Inject + private LdapConnectionService ldapConnectionService; + + /** + * Facilitating the instantiation + */ + @Inject + public DefaultLdapConfigurationValidatorService() { + } + + @Override + public void checkConnection(LdapConnection ldapConnection, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException { + try { + bind(ambariLdapConfiguration, ldapConnection); + } catch (LdapException e) { + LOGGER.error("Could not connect to the LDAP server", e); + 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 testUserName the test username + * @param testPassword the test password + * @param ambariLdapConfiguration configuration instance holding ldap configuration details + * @return the DN of the test user + * @throws AmbariException if the attributes are not valid or any errors occurs + */ + @Override + public String checkUserAttributes(LdapConnection ldapConnection, String testUserName, String testPassword, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException { + SearchCursor searchCursor = null; + String userDn = null; + try { + LOGGER.info("Checking user attributes for user {} r ...", testUserName); + + // bind anonimously or with manager data + bind(ambariLdapConfiguration, ldapConnection); + + // 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(), testUserName)) + .toString(); + + LOGGER.info("Searching for the user: {} using the search filter: {}", testUserName, filter); + EntryCursor entryCursor = ldapConnection.search(new Dn(ambariLdapConfiguration.userSearchBase()), filter, SearchScope.SUBTREE); + + // collecting search result entries + List<Entry> users = Lists.newArrayList(); + for (Entry entry : entryCursor) { + users.add(entry); + userDn = entry.getDn().getNormName(); + } + + // 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("User attributes validation failed.", e); + throw new AmbariLdapException(e.getMessage(), e); + + } finally { + closeResources(ldapConnection, searchCursor); + } + return userDn; + } + + + @Override + public Set<String> checkGroupAttributes(LdapConnection ldapConnection, String userDn, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException { + SearchCursor searchCursor = null; + Set<Response> groupResponses = Sets.newHashSet(); + + try { + LOGGER.info("Checking group attributes for user dn {} ...", userDn); + + bind(ambariLdapConfiguration, ldapConnection); + + // set up a filter based on the provided attributes + String filter = FilterBuilder.and( + FilterBuilder.equal(SchemaConstants.OBJECT_CLASS_AT, ambariLdapConfiguration.groupObjectClass()), + FilterBuilder.equal(ambariLdapConfiguration.groupMemberAttribute(), userDn) + ).toString(); + + LOGGER.info("Searching for the groups the user dn: {} is member of using the search filter: {}", userDn, filter); + + // assemble a search request + SearchRequest searchRequest = new SearchRequestImpl(); + searchRequest.setFilter(filter); + searchRequest.setBase(new Dn(ambariLdapConfiguration.groupSearchBase())); + searchRequest.setScope(SearchScope.SUBTREE); + searchRequest.addAttributes(ambariLdapConfiguration.groupMemberAttribute(), ambariLdapConfiguration.groupNameAttribute()); + + // perform the search + searchCursor = ldapConnection.search(searchRequest); + + for (Response response : searchCursor) { + groupResponses.add(response); + } + + } catch (Exception e) { + + LOGGER.error("User attributes validation failed.", e); + throw new AmbariLdapException(e.getMessage(), e); + + } finally { + closeResources(ldapConnection, searchCursor); + } + + return processGroupResults(groupResponses, ambariLdapConfiguration); + } + + /** + * Binds to the LDAP server (anonimously or wit manager credentials) + * + * @param ambariLdapConfiguration configuration instance + * @param connection connection instance + * @throws LdapException if the bind operation fails + */ + private void bind(AmbariLdapConfiguration ambariLdapConfiguration, LdapConnection connection) throws LdapException { + LOGGER.info("Connecting to LDAP ...."); + 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"); + } + LOGGER.info("Connected to LDAP."); + } + + + /** + * Extracts meaningful values from the search result. + * + * @param groupResponses the result entries returned by the search + * @param ambariLdapConfiguration holds the keys of the meaningful attributes + * @return a set with the group names the test user belongs to + */ + private Set<String> processGroupResults(Set<Response> groupResponses, AmbariLdapConfiguration ambariLdapConfiguration) { + Set<String> groupStrSet = Sets.newHashSet(); + for (Response response : groupResponses) { + Entry entry = ((SearchResultEntryDecorator) response).getEntry(); + groupStrSet.add(entry.get(ambariLdapConfiguration.groupNameAttribute()).get().getString()); + } + + LOGGER.debug("Extracted group names from group search responses: {}", groupStrSet); + return groupStrSet; + } + + private void closeResources(LdapConnection connection, SearchCursor searchCursor) { + LOGGER.debug("Housekeeping: closing the connection and the search cursor ..."); + + if (null != searchCursor) { + // this method is idempotent + searchCursor.close(); + } + + if (null != connection) { + try { + connection.close(); + } catch (IOException e) { + LOGGER.error("Exception occurred while closing the connection", e); + } + } + } + +} + + + http://git-wip-us.apache.org/repos/asf/ambari/blob/6c3dcc78/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java new file mode 100644 index 0000000..ced52fc --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConnectionService.java @@ -0,0 +1,63 @@ +/* + * 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.ldap.service.ads; + +import javax.inject.Singleton; + +import org.apache.ambari.server.ldap.AmbariLdapConfiguration; +import org.apache.ambari.server.ldap.service.LdapConnectionService; +import org.apache.directory.ldap.client.api.LdapConnectionConfig; +import org.apache.directory.ldap.client.api.LdapNetworkConnection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Singleton +public class DefaultLdapConnectionService implements LdapConnectionService { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConnectionService.class); + + @Override + public LdapNetworkConnection createLdapConnection(AmbariLdapConfiguration ambariLdapConfiguration) { + LOGGER.debug("Creating ldap connection instance from: {}", ambariLdapConfiguration); + return new LdapNetworkConnection(getLdapConnectionConfig(ambariLdapConfiguration)); + } + + private 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/6c3dcc78/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java deleted file mode 100644 index 663ea12..0000000 --- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ad/DefaultLdapConfigurationValidatorServiceTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.ldap.AmbariLdapConfiguration; -import org.apache.ambari.server.ldap.LdapConfigurationValidatorService; -import org.apache.ambari.server.ldap.service.LdapConnectionService; -import org.apache.directory.api.ldap.model.cursor.EntryCursor; -import org.apache.directory.api.ldap.model.entry.Entry; -import org.apache.directory.api.ldap.model.message.SearchScope; -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.shared.ldap.constants.SchemaConstants; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.Maps; - -public class DefaultLdapConfigurationValidatorServiceTest { - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class); - private static final String TEST_USER = "einstein"; - - LdapConfigurationValidatorService ldapConfigurationValidatorService = new DefaultLdapConfigurationValidatorService(); - - - @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 { - // GIVEN - Map<String, Object> ldapPropsMap = Maps.newHashMap(); - - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true"); - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com"); - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389"); - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com"); - - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC); - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT); - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_SEARCH_BASE.propertyName(), "dc=example,dc=com"); - - - AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap); - LdapConnectionService connectionService = new DefaultLdapConnectionService(); - LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration); - - ldapConfigurationValidatorService.checkUserAttributes(ldapConnection, "einstein", "", ambariLdapConfiguration); - } - - @Test - public void testRetrieveGorupsForuser() throws Exception { - // GIVEN - Map<String, Object> ldapPropsMap = Maps.newHashMap(); - - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true"); - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com"); - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389"); - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com"); - - - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_OBJECT_CLASS.propertyName(), SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC); - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_NAME_ATTRIBUTE.propertyName(), SchemaConstants.CN_AT); - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE.propertyName(), SchemaConstants.UNIQUE_MEMBER_AT); - ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_SEARCH_BASE.propertyName(), "dc=example,dc=com"); - - - AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap); - LdapConnectionService connectionService = new DefaultLdapConnectionService(); - LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration); - - ldapConfigurationValidatorService.checkGroupAttributes(ldapConnection, "uid=einstein,dc=example,dc=com", ambariLdapConfiguration); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/6c3dcc78/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java new file mode 100644 index 0000000..1c7f75d --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationValidatorServiceTest.java @@ -0,0 +1,113 @@ +/* + * 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.ads; + +import static org.junit.Assert.assertNotNull; + +import java.util.Map; + +import org.apache.ambari.server.ldap.AmbariLdapConfiguration; +import org.apache.ambari.server.ldap.LdapConfigurationValidatorService; +import org.apache.ambari.server.ldap.service.LdapConnectionService; +import org.apache.directory.api.ldap.model.constants.SchemaConstants; +import org.apache.directory.api.ldap.model.cursor.EntryCursor; +import org.apache.directory.api.ldap.model.entry.Entry; +import org.apache.directory.api.ldap.model.message.SearchScope; +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.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Maps; + +public class DefaultLdapConfigurationValidatorServiceTest { + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapConfigurationValidatorService.class); + private static final String TEST_USER = "einstein"; + + LdapConfigurationValidatorService ldapConfigurationValidatorService = new DefaultLdapConfigurationValidatorService(); + + + @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 { + // GIVEN + Map<String, Object> ldapPropsMap = Maps.newHashMap(); + + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true"); + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com"); + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389"); + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com"); + + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_OBJECT_CLASS.propertyName(), SchemaConstants.PERSON_OC); + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_NAME_ATTRIBUTE.propertyName(), SchemaConstants.UID_AT); + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.USER_SEARCH_BASE.propertyName(), "dc=example,dc=com"); + + + AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap); + LdapConnectionService connectionService = new DefaultLdapConnectionService(); + LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration); + + ldapConfigurationValidatorService.checkUserAttributes(ldapConnection, "einstein", "", ambariLdapConfiguration); + } + + @Test + public void testRetrieveGorupsForuser() throws Exception { + // GIVEN + Map<String, Object> ldapPropsMap = Maps.newHashMap(); + + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BIND_ANONIMOUSLY.propertyName(), "true"); + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_HOST.propertyName(), "ldap.forumsys.com"); + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.LDAP_SERVER_PORT.propertyName(), "389"); + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.BASE_DN.propertyName(), "dc=example,dc=com"); + + + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_OBJECT_CLASS.propertyName(), SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC); + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_NAME_ATTRIBUTE.propertyName(), SchemaConstants.CN_AT); + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_MEMBER_ATTRIBUTE.propertyName(), SchemaConstants.UNIQUE_MEMBER_AT); + ldapPropsMap.put(AmbariLdapConfiguration.LdapConfigProperty.GROUP_SEARCH_BASE.propertyName(), "dc=example,dc=com"); + + + AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapPropsMap); + LdapConnectionService connectionService = new DefaultLdapConnectionService(); + LdapNetworkConnection ldapConnection = connectionService.createLdapConnection(ambariLdapConfiguration); + + ldapConfigurationValidatorService.checkGroupAttributes(ldapConnection, "uid=einstein,dc=example,dc=com", ambariLdapConfiguration); + } +} \ No newline at end of file