From f2b97db0f9409b3a45eb58d88d04f27709e3ace0 Mon Sep 17 00:00:00 2001 From: Abhinandan Prateek Date: Tue, 19 Feb 2013 15:36:39 +0530 Subject: [PATCH] CLOUDSTACK-1172: LDAP enhancements --- .../configuration/ConfigurationService.java | 2 + .../api/command/admin/ldap/LDAPConfigCmd.java | 61 ++++++++++++++++--- .../api/response/LDAPConfigResponse.java | 2 +- .../server/auth/LDAPUserAuthenticator.java | 9 ++- .../ConfigurationManagerImpl.java | 33 ++++++++-- .../vpc/MockConfigurationManagerImpl.java | 9 +++ 6 files changed, 99 insertions(+), 17 deletions(-) diff --git a/api/src/com/cloud/configuration/ConfigurationService.java b/api/src/com/cloud/configuration/ConfigurationService.java index a9595fe7574..e63fcece525 100644 --- a/api/src/com/cloud/configuration/ConfigurationService.java +++ b/api/src/com/cloud/configuration/ConfigurationService.java @@ -264,6 +264,8 @@ public interface ConfigurationService { boolean removeLDAP(LDAPRemoveCmd cmd); + LDAPConfigCmd listLDAPConfig(LDAPConfigCmd cmd); + /** * @param offering * @return diff --git a/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPConfigCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPConfigCmd.java index fbe8ab000e6..2976de4bf28 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPConfigCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPConfigCmd.java @@ -31,6 +31,7 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.InvalidParameterValueException; import com.cloud.user.Account; @APICommand(name = "ldapConfig", description="Configure the LDAP context for this site.", responseObject=LDAPConfigResponse.class, since="3.0.0") @@ -43,7 +44,10 @@ public class LDAPConfigCmd extends BaseCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name=ApiConstants.HOST_NAME, type=CommandType.STRING, required=true, description="Hostname or ip address of the ldap server eg: my.ldap.com") + @Parameter(name=ApiConstants.LIST_ALL, type=CommandType.STRING, description="Hostname or ip address of the ldap server eg: my.ldap.com") + private String 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.") @@ -52,10 +56,10 @@ public class LDAPConfigCmd extends BaseCmd { @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, required=true, description="The search base defines the starting point for the search in the directory tree Example: dc=cloud,dc=com.") + @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, required=true, description="You specify a query filter here, which narrows down the users, who can be part of this domain.") + @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.") @@ -74,6 +78,10 @@ public class LDAPConfigCmd extends BaseCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// + public String getListAll() { + return listall == null ? "false" : listall; + } + public String getBindPassword() { return bindPassword; } @@ -82,30 +90,56 @@ public class LDAPConfigCmd extends BaseCmd { return bindDN; } + public void setBindDN(String bdn) { + this.bindDN=bdn; + } + public String getQueryFilter() { return queryFilter; } + public void setQueryFilter(String queryFilter) { + this.queryFilter=queryFilter; + } public String getSearchBase() { return searchBase; } + public void setSearchBase(String searchBase) { + this.searchBase=searchBase; + } + public Boolean getUseSSL() { - return useSSL == null ? Boolean.FALSE : Boolean.TRUE; + 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; @@ -122,12 +156,25 @@ public class LDAPConfigCmd extends BaseCmd { InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { try { - boolean result = _configService.updateLDAP(this); - if (result){ - LDAPConfigResponse lr = _responseGenerator.createLDAPConfigResponse(getHostname(), getPort(), getUseSSL(), getQueryFilter(), getSearchBase(), getBindDN()); + if ("true".equalsIgnoreCase(getListAll())){ + // return the existing conf + LDAPConfigCmd cmd = _configService.listLDAPConfig(this); + LDAPConfigResponse lr = _responseGenerator.createLDAPConfigResponse(cmd.getHostname(), cmd.getPort(), cmd.getUseSSL(), + cmd.getQueryFilter(), cmd.getSearchBase(), cmd.getBindDN()); lr.setResponseName(getCommandName()); this.setResponseObject(lr); } + else if (getHostname()==null || getSearchBase() == null || getQueryFilter() == null) { + throw new InvalidParameterValueException("You need to provide hostname, serachbase and queryfilter to configure your LDAP server"); + } + else { + boolean result = _configService.updateLDAP(this); + if (result){ + LDAPConfigResponse lr = _responseGenerator.createLDAPConfigResponse(getHostname(), getPort(), getUseSSL(), getQueryFilter(), getSearchBase(), getBindDN()); + lr.setResponseName(getCommandName()); + this.setResponseObject(lr); + } + } } catch (NamingException ne){ ne.printStackTrace(); diff --git a/api/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java b/api/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java index aa10229f2bd..bbeec630d81 100644 --- a/api/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java +++ b/api/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java @@ -30,7 +30,7 @@ public class LDAPConfigResponse extends BaseResponse { @SerializedName(ApiConstants.PORT) @Param(description="Specify the LDAP port if required, default is 389") private String port; - @SerializedName(ApiConstants.PORT) @Param(description="Check Use SSL if the external LDAP server is configured for LDAP over SSL") + @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") diff --git a/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java b/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java index fb0273e6ea3..61eebe5fc93 100644 --- a/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java +++ b/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java @@ -66,7 +66,7 @@ public class LDAPUserAuthenticator extends DefaultUserAuthenticator { String port = _configDao.getValue(LDAPParams.port.toString()); String queryFilter = _configDao.getValue(LDAPParams.queryfilter.toString()); String searchBase = _configDao.getValue(LDAPParams.searchbase.toString()); - String useSSL = _configDao.getValue(LDAPParams.usessl.toString()); + Boolean useSSL = Boolean.valueOf(_configDao.getValue(LDAPParams.usessl.toString())); String bindDN = _configDao.getValue(LDAPParams.dn.toString()); String bindPasswd = _configDao.getValue(LDAPParams.passwd.toString()); String trustStore = _configDao.getValue(LDAPParams.truststore.toString()); @@ -77,7 +77,7 @@ public class LDAPUserAuthenticator extends DefaultUserAuthenticator { Hashtable env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); String protocol = "ldap://" ; - if (new Boolean(useSSL)){ + if (useSSL){ env.put(Context.SECURITY_PROTOCOL, "ssl"); protocol="ldaps://" ; System.setProperty("javax.net.ssl.trustStore", trustStore); @@ -123,7 +123,7 @@ public class LDAPUserAuthenticator extends DefaultUserAuthenticator { env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); protocol = "ldap://" ; - if (new Boolean(useSSL)){ + if (useSSL){ env.put(Context.SECURITY_PROTOCOL, "ssl"); protocol="ldaps://" ; } @@ -135,8 +135,7 @@ public class LDAPUserAuthenticator extends DefaultUserAuthenticator { ctx.close(); } catch (NamingException ne) { - ne.printStackTrace(); - s_logger.warn("Authentication failed due to " + ne.getMessage()); + s_logger.warn("Authentication Failed ! " + ne.getMessage() + (ne.getCause() != null ? ("; Caused by:" + ne.getCause().getMessage()) : "")); return false; } catch (Exception e){ diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 074675cdd33..b886bedbc48 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1246,6 +1246,27 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return true; } + + @Override + @DB + public LDAPConfigCmd listLDAPConfig(LDAPConfigCmd cmd) { + String hostname = _configDao.getValue(LDAPParams.hostname.toString()); + cmd.setHostname(hostname == null ? "" : hostname); + String port = _configDao.getValue(LDAPParams.port.toString()); + cmd.setPort(port == null ? 0 : Integer.valueOf(port)); + String queryFilter = _configDao.getValue(LDAPParams.queryfilter.toString()); + cmd.setQueryFilter(queryFilter == null ? "" : queryFilter); + String searchBase = _configDao.getValue(LDAPParams.searchbase.toString()); + cmd.setSearchBase(searchBase == null ? "" : searchBase); + String useSSL = _configDao.getValue(LDAPParams.usessl.toString()); + cmd.setUseSSL(useSSL == null ? Boolean.FALSE : Boolean.valueOf(useSSL)); + String binddn = _configDao.getValue(LDAPParams.dn.toString()); + cmd.setBindDN(binddn == null ? "" : binddn); + String truststore = _configDao.getValue(LDAPParams.truststore.toString()); + cmd.setTrustStore(truststore == null ? "" : truststore); + return cmd; + } + @Override @DB public boolean updateLDAP(LDAPConfigCmd cmd) { @@ -1265,11 +1286,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("If you specify a bind name then you need to provide bind password too."); } + // check query filter if it contains valid substitution + if (!queryFilter.contains("%u") && !queryFilter.contains("%n") && !queryFilter.contains("%e")){ + throw new InvalidParameterValueException("QueryFilter should contain at least one of the substitutions: %u, %n or %e: " + queryFilter); + } + // check if the info is correct Hashtable env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); String protocol = "ldap://"; - if (new Boolean(useSSL)) { + if (useSSL) { env.put(Context.SECURITY_PROTOCOL, "ssl"); protocol = "ldaps://"; if (trustStore == null || trustStorePassword == null) { @@ -1288,7 +1314,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati DirContext ctx = new InitialDirContext(env); ctx.close(); - // store the result in DB COnfiguration + // store the result in DB Configuration ConfigurationVO cvo = _configDao.findByName(LDAPParams.hostname.toString()); if (cvo == null) { cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.hostname.toString(), null, "Hostname or ip address of the ldap server eg: my.ldap.com"); @@ -1356,8 +1382,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati s_logger.debug("The ldap server is configured: " + hostname); } catch (NamingException ne) { - ne.printStackTrace(); - throw new InvalidParameterValueException("Naming Exception, check you ldap data ! " + ne.getMessage() + (ne.getCause() != null ? ("Caused by:" + ne.getCause().getMessage()) : "")); + throw new InvalidParameterValueException("Naming Exception, check you ldap data ! " + ne.getMessage() + (ne.getCause() != null ? ("; Caused by:" + ne.getCause().getMessage()) : "")); } return true; } diff --git a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java index 574ce0a0352..180138ac136 100644 --- a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java +++ b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java @@ -365,6 +365,15 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu return false; } + /* (non-Javadoc) + * @see com.cloud.configuration.ConfigurationService#listLDAPConfig(org.apache.cloudstack.api.commands.LDAPConfigCmd) + */ + @Override + public LDAPConfigCmd listLDAPConfig(LDAPConfigCmd cmd) { + // TODO Auto-generated method stub + return null; + } + /* (non-Javadoc) * @see com.cloud.configuration.ConfigurationService#isOfferingForVpc(com.cloud.offering.NetworkOffering) */