diff --git a/conf/ldap.conf b/conf/ldap.conf index deb1a06a1d0479..9388ae7ee50b1e 100644 --- a/conf/ldap.conf +++ b/conf/ldap.conf @@ -44,6 +44,9 @@ ldap_group_basedn = ou=group,dc=domain,dc=com # ldap_user_cache_timeout_s = 5 * 60; +## ldap_use_ssl - use secured connection to LDAP server if required (disabled by default). Note: When enabling SSL, ensure ldap_port is set appropriately (typically 636 for LDAPS instead of 389 for LDAP). +# ldap_use_ssl = false + # LDAP pool configuration # https://docs.spring.io/spring-ldap/docs/2.3.3.RELEASE/reference/#pool-configuration # ldap_pool_max_active = 8 diff --git a/fe/fe-common/src/main/java/org/apache/doris/common/LdapConfig.java b/fe/fe-common/src/main/java/org/apache/doris/common/LdapConfig.java index 9499fcc2a1b88f..881840696dcde8 100644 --- a/fe/fe-common/src/main/java/org/apache/doris/common/LdapConfig.java +++ b/fe/fe-common/src/main/java/org/apache/doris/common/LdapConfig.java @@ -157,4 +157,22 @@ public class LdapConfig extends ConfigBase { */ @ConfigBase.ConfField public static boolean ldap_pool_test_while_idle = true; + + /** + * Flag to enable usage of LDAPS. + */ + @ConfigBase.ConfField + public static boolean ldap_use_ssl = false; + + /** + * The method constructs the correct URL connection string for the specified host and port depending on + * the value of the {@code ldap_use_ssl} property. + * If {@code ldap_use_ssl} is true, LDAPS is used as the protocol. + * If {@code ldap_use_ssl} is false or not specified, LDAP is used as the protocol. + * @param hostPortInAccessibleFormat the host and port in accessible format (for example, "host:port") + * @return the LDAP or LDAPS connection URL string + */ + public static String getConnectionURL(String hostPortInAccessibleFormat) { + return ((LdapConfig.ldap_use_ssl ? "ldaps" : "ldap") + "://" + hostPortInAccessibleFormat); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapClient.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapClient.java index d5641ac6c09b82..79248ab0212ecd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapClient.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapClient.java @@ -65,8 +65,8 @@ public ClientInfo(String ldapPassword) { private void setLdapTemplateNoPool(String ldapPassword) { LdapContextSource contextSource = new LdapContextSource(); - String url = "ldap://" + NetUtils - .getHostPortInAccessibleFormat(LdapConfig.ldap_host, LdapConfig.ldap_port); + String url = LdapConfig.getConnectionURL( + NetUtils.getHostPortInAccessibleFormat(LdapConfig.ldap_host, LdapConfig.ldap_port)); contextSource.setUrl(url); contextSource.setUserDn(LdapConfig.ldap_admin_name); @@ -78,8 +78,8 @@ private void setLdapTemplateNoPool(String ldapPassword) { private void setLdapTemplatePool(String ldapPassword) { LdapContextSource contextSource = new LdapContextSource(); - String url = "ldap://" + NetUtils - .getHostPortInAccessibleFormat(LdapConfig.ldap_host, LdapConfig.ldap_port); + String url = LdapConfig.getConnectionURL( + NetUtils.getHostPortInAccessibleFormat(LdapConfig.ldap_host, LdapConfig.ldap_port)); contextSource.setUrl(url); contextSource.setUserDn(LdapConfig.ldap_admin_name); @@ -108,6 +108,7 @@ private void setLdapTemplatePool(String ldapPassword) { public boolean checkUpdate(String ldapPassword) { return this.ldapPassword == null || !this.ldapPassword.equals(ldapPassword); } + } private void init() { diff --git a/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java b/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java index 866a84e752819d..c0d6c36f83ba99 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java @@ -19,9 +19,11 @@ import org.apache.doris.common.Config; import org.apache.doris.common.LdapConfig; +import org.apache.doris.common.util.NetUtils; import mockit.Expectations; import mockit.Tested; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -43,6 +45,7 @@ public void setUp() { LdapConfig.ldap_user_basedn = "dc=baidu,dc=com"; LdapConfig.ldap_group_basedn = "ou=group,dc=baidu,dc=com"; LdapConfig.ldap_user_filter = "(&(uid={login}))"; + LdapConfig.ldap_use_ssl = false; } @Test @@ -95,4 +98,28 @@ public void testGetGroups() { }; Assert.assertEquals(1, ldapClient.getGroups("zhangsan").size()); } + + @Test + public void testSecuredProtocolIsUsed() { + //testing default case with not specified property ldap_use_ssl or it is specified as false + String insecureUrl = LdapConfig.getConnectionURL( + NetUtils.getHostPortInAccessibleFormat(LdapConfig.ldap_host, LdapConfig.ldap_port)); + + Assert.assertNotNull("connection URL should not be null", insecureUrl); + Assert.assertTrue("with ldap_use_ssl = false or not specified URL should start with ldap, but received: " + insecureUrl, + insecureUrl.startsWith("ldap://")); + + //testing new case with specified property ldap_use_ssl as true + LdapConfig.ldap_use_ssl = true; + String secureUrl = LdapConfig.getConnectionURL( + NetUtils.getHostPortInAccessibleFormat(LdapConfig.ldap_host, LdapConfig.ldap_port)); + Assert.assertNotNull("connection URL should not be null", secureUrl); + Assert.assertTrue("with ldap_use_ssl = true URL should start with ldaps, but received: " + secureUrl, + secureUrl.startsWith("ldaps://")); + } + + @After + public void tearDown() { + LdapConfig.ldap_use_ssl = false; // restoring default value for other tests + } }