From db4e0d688c0da04724e52a334891088b03420e3a Mon Sep 17 00:00:00 2001 From: Rajani Karuturi Date: Tue, 10 Dec 2013 13:36:35 +0530 Subject: [PATCH] CLOUDSTACK-5375 :ldapconfig and ldapRemove api's are not working Added support for 4.2 ldap apis Conflicts: plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java Signed-off-by: Abhinandan Prateek --- .../cloudstack/api/command/LDAPConfigCmd.java | 261 +++++++++++++ .../cloudstack/api/command/LDAPRemoveCmd.java | 77 ++++ .../api/response/LDAPConfigResponse.java | 115 ++++++ .../api/response/LDAPRemoveResponse.java | 30 ++ .../cloudstack/ldap/LdapManagerImpl.java | 364 +++++++++--------- 5 files changed, 655 insertions(+), 192 deletions(-) create mode 100644 plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPConfigCmd.java create mode 100644 plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPRemoveCmd.java create mode 100644 plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java create mode 100644 plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LDAPRemoveResponse.java diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPConfigCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPConfigCmd.java new file mode 100644 index 00000000000..3faf8b768b2 --- /dev/null +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPConfigCmd.java @@ -0,0 +1,261 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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.cloudstack.api.command; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.LDAPConfigResponse; +import org.apache.cloudstack.api.response.LdapConfigurationResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.config.impl.ConfigurationVO; +import org.apache.cloudstack.ldap.LdapConfiguration; +import org.apache.cloudstack.ldap.LdapConfigurationVO; +import org.apache.cloudstack.ldap.LdapManager; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.log4j.Logger; + +import com.cloud.exception.*; +import com.cloud.user.Account; +import com.cloud.utils.Pair; + +/** + * @deprecated as of 4.3 use the new api {@link LdapAddConfigurationCmd} + */ +@Deprecated +@APICommand(name = "ldapConfig", description = "Configure the LDAP context for this site.", responseObject = LDAPConfigResponse.class, since = "3.0.0") +public class LDAPConfigCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(LDAPConfigCmd.class.getName()); + + private static final String s_name = "ldapconfigresponse"; + + @Inject + private ConfigurationDao _configDao; + + @Inject + private LdapManager _ldapManager; + + @Inject + private LdapConfiguration _ldapConfiguration; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + @Parameter(name = ApiConstants.LIST_ALL, type = CommandType.BOOLEAN, description = "If true return current LDAP configuration") + private Boolean listAll; + + @Parameter(name = ApiConstants.HOST_NAME, type = CommandType.STRING, description = "Hostname or ip address of the ldap server eg: my.ldap.com") + private String hostname; + + @Parameter(name = ApiConstants.PORT, type = CommandType.INTEGER, description = "Specify the LDAP port if required, default is 389.") + private Integer port = 0; + + @Parameter(name = ApiConstants.USE_SSL, type = CommandType.BOOLEAN, description = "Check Use SSL if the external LDAP server is configured for LDAP over SSL.") + private Boolean useSSL; + + @Parameter(name = ApiConstants.SEARCH_BASE, type = CommandType.STRING, description = "The search base defines the starting point for the search in the directory tree Example: dc=cloud,dc=com.") + private String searchBase; + + @Parameter(name = ApiConstants.QUERY_FILTER, type = CommandType.STRING, description = "You specify a query filter here, which narrows down the users, who can be part of this domain.") + private String queryFilter; + + @Parameter(name = ApiConstants.BIND_DN, type = CommandType.STRING, description = "Specify the distinguished name of a user with the search permission on the directory.") + private String bindDN; + + @Parameter(name = ApiConstants.BIND_PASSWORD, type = CommandType.STRING, description = "Enter the password.") + private String bindPassword; + + @Parameter(name = ApiConstants.TRUST_STORE, type = CommandType.STRING, description = "Enter the path to trust certificates store.") + private String trustStore; + + @Parameter(name = ApiConstants.TRUST_STORE_PASSWORD, type = CommandType.STRING, description = "Enter the password for trust store.") + private String trustStorePassword; + + public Boolean getListAll() { + return listAll == null ? Boolean.FALSE : listAll; + } + + public String getBindPassword() { + return bindPassword; + } + + public String getBindDN() { + return bindDN; + } + + public void setBindDN(String bdn) { + this.bindDN = bdn; + } + + public String getQueryFilter() { + return queryFilter; + } + + public void setQueryFilter(String queryFilter) { + this.queryFilter = StringEscapeUtils.unescapeHtml(queryFilter); + } + + public String getSearchBase() { + return searchBase; + } + + public void setSearchBase(String searchBase) { + this.searchBase = searchBase; + } + + public Boolean getUseSSL() { + return useSSL == null ? Boolean.FALSE : useSSL; + } + + public void setUseSSL(Boolean useSSL) { + this.useSSL = useSSL; + } + + public String getHostname() { + return hostname; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + + public Integer getPort() { + return port <= 0 ? 389 : port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public String getTrustStore() { + return trustStore; + } + + public void setTrustStore(String trustStore) { + this.trustStore = trustStore; + } + + public String getTrustStorePassword() { + return trustStorePassword; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + if (getListAll()) { + // return the existing conf + + LdapListConfigurationCmd listConfigurationCmd = new LdapListConfigurationCmd(_ldapManager); + Pair, Integer> result = _ldapManager.listConfigurations(listConfigurationCmd); + ListResponse response = new ListResponse(); + List responses = new ArrayList(); + + if (result.second() > 0) { + boolean useSSlConfig = _ldapConfiguration.getSSLStatus(); + String searchBaseConfig = _ldapConfiguration.getBaseDn(); + String bindDnConfig = _ldapConfiguration.getBindPrincipal(); + for (LdapConfigurationVO ldapConfigurationVO : result.first()) { + responses.add(this.createLDAPConfigResponse(ldapConfigurationVO.getHostname(), ldapConfigurationVO.getPort(), useSSlConfig, null, searchBaseConfig, + bindDnConfig)); + } + } + response.setResponses(responses); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else if (getHostname() == null || getPort() == null) { + throw new InvalidParameterValueException("You need to provide hostname, port to configure your LDAP server"); + } else { + boolean result = this.updateLDAP(); + if (result) { + LDAPConfigResponse lr = this.createLDAPConfigResponse(getHostname(), getPort(), getUseSSL(), getQueryFilter(), getSearchBase(), getBindDN()); + lr.setResponseName(getCommandName()); + this.setResponseObject(lr); + } + } + + } + + private LDAPConfigResponse createLDAPConfigResponse(String hostname, Integer port, Boolean useSSL, String queryFilter, String searchBase, String bindDN) { + LDAPConfigResponse lr = new LDAPConfigResponse(); + lr.setHostname(hostname); + lr.setPort(port.toString()); + lr.setUseSSL(useSSL.toString()); + lr.setQueryFilter(queryFilter); + lr.setBindDN(bindDN); + lr.setSearchBase(searchBase); + lr.setObjectName("ldapconfig"); + return lr; + } + + private boolean updateLDAP() { + LdapConfigurationResponse response = _ldapManager.addConfiguration(hostname, port); + + /** + * There is no query filter now. It is derived from ldap.user.object and ldap.search.group.principle + */ +// ConfigurationVO cvo = _configDao.findByName(LDAPParams.queryfilter.toString()); +// _configDao.update(cvo.getName(),cvo.getCategory(),getQueryFilter()); + + ConfigurationVO cvo = _configDao.findByName("ldap.basedn"); + _configDao.update(cvo.getName(), cvo.getCategory(), getSearchBase()); + + /** + * There is no ssl now. it is derived from the presence of trust store and password + */ +// cvo = _configDao.findByName(LDAPParams.usessl.toString()); +// _configDao.update(cvo.getName(),cvo.getCategory(),getUseSSL().toString()); + + cvo = _configDao.findByName("ldap.bind.principal"); + _configDao.update(cvo.getName(), cvo.getCategory(), getBindDN()); + + cvo = _configDao.findByName("ldap.bind.password"); + _configDao.update(cvo.getName(), cvo.getCategory(), getBindPassword()); + + cvo = _configDao.findByName("ldap.truststore"); + _configDao.update(cvo.getName(), cvo.getCategory(), getTrustStore()); + + cvo = _configDao.findByName("ldap.truststore.password"); + _configDao.update(cvo.getName(), cvo.getCategory(), getTrustStorePassword()); + + return true; + } + + private List listLDAPConfig() { + + LdapListConfigurationCmd listConfigurationCmd = new LdapListConfigurationCmd(_ldapManager); + Pair, Integer> result = _ldapManager.listConfigurations(listConfigurationCmd); + return result.first(); + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + +} diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPRemoveCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPRemoveCmd.java new file mode 100644 index 00000000000..535a545ade7 --- /dev/null +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPRemoveCmd.java @@ -0,0 +1,77 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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.cloudstack.api.command; + +import java.util.List; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.response.LDAPConfigResponse; +import org.apache.cloudstack.api.response.LDAPRemoveResponse; +import org.apache.cloudstack.ldap.LdapConfigurationVO; +import org.apache.cloudstack.ldap.LdapManager; +import org.apache.log4j.Logger; + +import com.cloud.user.Account; +import com.cloud.utils.Pair; + +/** + * @deprecated as of 4.3 use the new api {@link LdapDeleteConfigurationCmd} + */ +@Deprecated +@APICommand(name = "ldapRemove", description = "Remove the LDAP context for this site.", responseObject = LDAPConfigResponse.class, since = "3.0.1") +public class LDAPRemoveCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(LDAPRemoveCmd.class.getName()); + + @Inject + private LdapManager _ldapManager; + + private static final String s_name = "ldapremoveresponse"; + + @Override + public void execute() { + boolean result = this.removeLDAP(); + if (result) { + LDAPRemoveResponse lr = new LDAPRemoveResponse(); + lr.setObjectName("ldapremove"); + lr.setResponseName(getCommandName()); + this.setResponseObject(lr); + } + } + + private boolean removeLDAP() { + LdapListConfigurationCmd listConfigurationCmd = new LdapListConfigurationCmd(_ldapManager); + Pair, Integer> result = _ldapManager.listConfigurations(listConfigurationCmd); + for (LdapConfigurationVO config : result.first()) { + _ldapManager.deleteConfiguration(config.getHostname()); + } + return true; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + +} diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java new file mode 100644 index 00000000000..8570bacab06 --- /dev/null +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java @@ -0,0 +1,115 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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.cloudstack.api.response; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +/** + * @deprecated as of 4.3 along with the api {@link org.apache.cloudstack.api.command.LDAPConfigCmd} + */ +@Deprecated +public class LDAPConfigResponse extends BaseResponse { + + @SerializedName(ApiConstants.HOST_NAME) + @Param(description = "Hostname or ip address of the ldap server eg: my.ldap.com") + private String hostname; + + @SerializedName(ApiConstants.PORT) + @Param(description = "Specify the LDAP port if required, default is 389") + private String port; + + @SerializedName(ApiConstants.USE_SSL) + @Param(description = "Check Use SSL if the external LDAP server is configured for LDAP over SSL") + private String useSSL; + + @SerializedName(ApiConstants.SEARCH_BASE) + @Param(description = "The search base defines the starting point for the search in the directory tree Example: dc=cloud,dc=com") + private String searchBase; + + @SerializedName(ApiConstants.QUERY_FILTER) + @Param(description = "You specify a query filter here, which narrows down the users, who can be part of this domain") + private String queryFilter; + + @SerializedName(ApiConstants.BIND_DN) + @Param(description = "Specify the distinguished name of a user with the search permission on the directory") + private String bindDN; + + @SerializedName(ApiConstants.BIND_PASSWORD) + @Param(description = "DN password") + private String bindPassword; + + public String getHostname() { + return hostname; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getUseSSL() { + return useSSL; + } + + public void setUseSSL(String useSSL) { + this.useSSL = useSSL; + } + + public String getSearchBase() { + return searchBase; + } + + public void setSearchBase(String searchBase) { + this.searchBase = searchBase; + } + + public String getQueryFilter() { + return queryFilter; + } + + public void setQueryFilter(String queryFilter) { + this.queryFilter = queryFilter; + } + + public String getBindDN() { + return bindDN; + } + + public void setBindDN(String bindDN) { + this.bindDN = bindDN; + } + + public String getBindPassword() { + return bindPassword; + } + + public void setBindPassword(String bindPassword) { + this.bindPassword = bindPassword; + } + +} diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LDAPRemoveResponse.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LDAPRemoveResponse.java new file mode 100644 index 00000000000..9b473d2f385 --- /dev/null +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LDAPRemoveResponse.java @@ -0,0 +1,30 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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.cloudstack.api.response; + +import org.apache.cloudstack.api.BaseResponse; + +/** + * @deprecated as of 4.3 along with the api {@link org.apache.cloudstack.api.command.LDAPRemoveCmd} + */ +@Deprecated +public class LDAPRemoveResponse extends BaseResponse { + + public LDAPRemoveResponse() { + super(); + } +} diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java index 891d62538ab..578ebce7f77 100644 --- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java @@ -38,205 +38,185 @@ import com.cloud.utils.Pair; @Component @Local(value = LdapManager.class) public class LdapManagerImpl implements LdapManager, LdapValidator { - private static final Logger s_logger = Logger - .getLogger(LdapManagerImpl.class.getName()); + private static final Logger s_logger = Logger.getLogger(LdapManagerImpl.class.getName()); - @Inject - private LdapConfigurationDao _ldapConfigurationDao; + @Inject + private LdapConfigurationDao _ldapConfigurationDao; - @Inject - private LdapContextFactory _ldapContextFactory; + @Inject + private LdapContextFactory _ldapContextFactory; - @Inject - private LdapUserManager _ldapUserManager; + @Inject + private LdapUserManager _ldapUserManager; - public LdapManagerImpl() { - super(); - } + public LdapManagerImpl() { + super(); + } - public LdapManagerImpl(final LdapConfigurationDao ldapConfigurationDao, - final LdapContextFactory ldapContextFactory, - final LdapUserManager ldapUserManager) { - super(); - _ldapConfigurationDao = ldapConfigurationDao; - _ldapContextFactory = ldapContextFactory; - _ldapUserManager = ldapUserManager; - } - - @Override - public LdapConfigurationResponse addConfiguration(final String hostname, - final int port) throws InvalidParameterValueException { - LdapConfigurationVO configuration = _ldapConfigurationDao - .findByHostname(hostname); - if (configuration == null) { - try { - final String providerUrl = "ldap://" + hostname + ":" + port; - _ldapContextFactory.createBindContext(providerUrl); - configuration = new LdapConfigurationVO(hostname, port); - _ldapConfigurationDao.persist(configuration); - s_logger.info("Added new ldap server with hostname: " - + hostname); - return new LdapConfigurationResponse(hostname, port); - } catch (final NamingException e) { - throw new InvalidParameterValueException( - "Unable to bind to the given LDAP server"); - } - } else { - throw new InvalidParameterValueException("Duplicate configuration"); - } - } - - @Override - public boolean canAuthenticate(final String username, final String password) { - final String escapedUsername = LdapUtils - .escapeLDAPSearchFilter(username); - try { - final LdapUser user = getUser(escapedUsername); - final String principal = user.getPrincipal(); - final DirContext context = _ldapContextFactory.createUserContext( - principal, password); - closeContext(context); - return true; - } catch (final NamingException e) { - s_logger.info("Failed to authenticate user: " + username - + ". incorrect password."); - return false; - } - } - - private void closeContext(final DirContext context) { - try { - if (context != null) { - context.close(); - } - } catch (final NamingException e) { - s_logger.warn(e.getMessage()); - } - } - - @Override - public LdapConfigurationResponse createLdapConfigurationResponse( - final LdapConfigurationVO configuration) { - final LdapConfigurationResponse response = new LdapConfigurationResponse(); - response.setHostname(configuration.getHostname()); - response.setPort(configuration.getPort()); - return response; - } - - @Override - public LdapUserResponse createLdapUserResponse(final LdapUser user) { - final LdapUserResponse response = new LdapUserResponse(); - response.setUsername(user.getUsername()); - response.setFirstname(user.getFirstname()); - response.setLastname(user.getLastname()); - response.setEmail(user.getEmail()); - response.setPrincipal(user.getPrincipal()); - response.setDomain(user.getDomain()); - return response; - } - - @Override - public LdapConfigurationResponse deleteConfiguration(final String hostname) - throws InvalidParameterValueException { - final LdapConfigurationVO configuration = _ldapConfigurationDao - .findByHostname(hostname); - if (configuration == null) { - throw new InvalidParameterValueException( - "Cannot find configuration with hostname " + hostname); - } else { - _ldapConfigurationDao.remove(configuration.getId()); - s_logger.info("Removed ldap server with hostname: " + hostname); - return new LdapConfigurationResponse(configuration.getHostname(), - configuration.getPort()); - } - } - - @Override - public List> getCommands() { - final List> cmdList = new ArrayList>(); - cmdList.add(LdapUserSearchCmd.class); - cmdList.add(LdapListUsersCmd.class); - cmdList.add(LdapAddConfigurationCmd.class); - cmdList.add(LdapDeleteConfigurationCmd.class); - cmdList.add(LdapListConfigurationCmd.class); - cmdList.add(LdapCreateAccountCmd.class); - cmdList.add(LdapImportUsersCmd.class); - return cmdList; - } - - @Override - public LdapUser getUser(final String username) throws NamingException { - DirContext context = null; - try { - context = _ldapContextFactory.createBindContext(); - - final String escapedUsername = LdapUtils - .escapeLDAPSearchFilter(username); - return _ldapUserManager.getUser(escapedUsername, context); - - } catch (final NamingException e) { - throw e; - } finally { - closeContext(context); - } - } - - @Override - public List getUsers() throws NoLdapUserMatchingQueryException { - DirContext context = null; - try { - context = _ldapContextFactory.createBindContext(); - return _ldapUserManager.getUsers(context); - } catch (final NamingException e) { - throw new NoLdapUserMatchingQueryException("*"); - } finally { - closeContext(context); - } - } - - @Override - public List getUsersInGroup(String groupName) throws NoLdapUserMatchingQueryException { - DirContext context = null; - try { - context = _ldapContextFactory.createBindContext(); - return _ldapUserManager.getUsersInGroup(groupName, context); - } catch (final NamingException e) { - throw new NoLdapUserMatchingQueryException("groupName=" + groupName); - } finally { - closeContext(context); - } + public LdapManagerImpl(final LdapConfigurationDao ldapConfigurationDao, final LdapContextFactory ldapContextFactory, final LdapUserManager ldapUserManager) { + super(); + _ldapConfigurationDao = ldapConfigurationDao; + _ldapContextFactory = ldapContextFactory; + _ldapUserManager = ldapUserManager; } @Override - public boolean isLdapEnabled() { - return listConfigurations(new LdapListConfigurationCmd(this)).second() > 0; - } + public LdapConfigurationResponse addConfiguration(final String hostname, final int port) throws InvalidParameterValueException { + LdapConfigurationVO configuration = _ldapConfigurationDao.findByHostname(hostname); + if (configuration == null) { + try { + final String providerUrl = "ldap://" + hostname + ":" + port; + _ldapContextFactory.createBindContext(providerUrl); + configuration = new LdapConfigurationVO(hostname, port); + _ldapConfigurationDao.persist(configuration); + s_logger.info("Added new ldap server with hostname: " + hostname); + return new LdapConfigurationResponse(hostname, port); + } catch (final NamingException e) { + throw new InvalidParameterValueException("Unable to bind to the given LDAP server"); + } + } else { + throw new InvalidParameterValueException("Duplicate configuration"); + } + } - @Override - public Pair, Integer> listConfigurations( - final LdapListConfigurationCmd cmd) { - final String hostname = cmd.getHostname(); - final int port = cmd.getPort(); - final Pair, Integer> result = _ldapConfigurationDao - .searchConfigurations(hostname, port); - return new Pair, Integer>( - result.first(), result.second()); - } + @Override + public boolean canAuthenticate(final String username, final String password) { + final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username); + try { + final LdapUser user = getUser(escapedUsername); + final String principal = user.getPrincipal(); + final DirContext context = _ldapContextFactory.createUserContext(principal, password); + closeContext(context); + return true; + } catch (final NamingException e) { + s_logger.info("Failed to authenticate user: " + username + ". incorrect password."); + return false; + } + } - @Override - public List searchUsers(final String username) - throws NoLdapUserMatchingQueryException { - DirContext context = null; - try { - context = _ldapContextFactory.createBindContext(); - final String escapedUsername = LdapUtils - .escapeLDAPSearchFilter(username); - return _ldapUserManager.getUsers("*" + escapedUsername + "*", - context); - } catch (final NamingException e) { - throw new NoLdapUserMatchingQueryException(username); - } finally { - closeContext(context); - } - } -} \ No newline at end of file + private void closeContext(final DirContext context) { + try { + if (context != null) { + context.close(); + } + } catch (final NamingException e) { + s_logger.warn(e.getMessage()); + } + } + + @Override + public LdapConfigurationResponse createLdapConfigurationResponse(final LdapConfigurationVO configuration) { + final LdapConfigurationResponse response = new LdapConfigurationResponse(); + response.setHostname(configuration.getHostname()); + response.setPort(configuration.getPort()); + return response; + } + + @Override + public LdapUserResponse createLdapUserResponse(final LdapUser user) { + final LdapUserResponse response = new LdapUserResponse(); + response.setUsername(user.getUsername()); + response.setFirstname(user.getFirstname()); + response.setLastname(user.getLastname()); + response.setEmail(user.getEmail()); + response.setPrincipal(user.getPrincipal()); + response.setDomain(user.getDomain()); + return response; + } + + @Override + public LdapConfigurationResponse deleteConfiguration(final String hostname) throws InvalidParameterValueException { + final LdapConfigurationVO configuration = _ldapConfigurationDao.findByHostname(hostname); + if (configuration == null) { + throw new InvalidParameterValueException("Cannot find configuration with hostname " + hostname); + } else { + _ldapConfigurationDao.remove(configuration.getId()); + s_logger.info("Removed ldap server with hostname: " + hostname); + return new LdapConfigurationResponse(configuration.getHostname(), configuration.getPort()); + } + } + + @Override + public List> getCommands() { + final List> cmdList = new ArrayList>(); + cmdList.add(LdapUserSearchCmd.class); + cmdList.add(LdapListUsersCmd.class); + cmdList.add(LdapAddConfigurationCmd.class); + cmdList.add(LdapDeleteConfigurationCmd.class); + cmdList.add(LdapListConfigurationCmd.class); + cmdList.add(LdapCreateAccountCmd.class); + cmdList.add(LdapImportUsersCmd.class); + cmdList.add(LDAPConfigCmd.class); + cmdList.add(LDAPRemoveCmd.class); + return cmdList; + } + + @Override + public LdapUser getUser(final String username) throws NamingException { + DirContext context = null; + try { + context = _ldapContextFactory.createBindContext(); + + final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username); + return _ldapUserManager.getUser(escapedUsername, context); + + } catch (final NamingException e) { + throw e; + } finally { + closeContext(context); + } + } + + @Override + public List getUsers() throws NoLdapUserMatchingQueryException { + DirContext context = null; + try { + context = _ldapContextFactory.createBindContext(); + return _ldapUserManager.getUsers(context); + } catch (final NamingException e) { + throw new NoLdapUserMatchingQueryException("*"); + } finally { + closeContext(context); + } + } + + @Override + public List getUsersInGroup(String groupName) throws NoLdapUserMatchingQueryException { + DirContext context = null; + try { + context = _ldapContextFactory.createBindContext(); + return _ldapUserManager.getUsersInGroup(groupName, context); + } catch (final NamingException e) { + throw new NoLdapUserMatchingQueryException("groupName=" + groupName); + } finally { + closeContext(context); + } + } + + @Override + public boolean isLdapEnabled() { + return listConfigurations(new LdapListConfigurationCmd(this)).second() > 0; + } + + @Override + public Pair, Integer> listConfigurations(final LdapListConfigurationCmd cmd) { + final String hostname = cmd.getHostname(); + final int port = cmd.getPort(); + final Pair, Integer> result = _ldapConfigurationDao.searchConfigurations(hostname, port); + return new Pair, Integer>(result.first(), result.second()); + } + + @Override + public List searchUsers(final String username) throws NoLdapUserMatchingQueryException { + DirContext context = null; + try { + context = _ldapContextFactory.createBindContext(); + final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username); + return _ldapUserManager.getUsers("*" + escapedUsername + "*", context); + } catch (final NamingException e) { + throw new NoLdapUserMatchingQueryException(username); + } finally { + closeContext(context); + } + } +}