diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java index 83907255641384..1cf7d4bb184912 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java @@ -742,7 +742,7 @@ public Env(boolean isCheckpointCatalog) { this.auth = new Auth(); this.accessManager = new AccessControllerManager(auth); - this.authenticatorManager = new AuthenticatorManager(AuthenticateType.getAuthTypeConfig()); + this.authenticatorManager = new AuthenticatorManager(AuthenticateType.getAuthTypeConfigString()); this.domainResolver = new DomainResolver(auth); this.metaContext = new MetaContext(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/AuthenticateType.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/AuthenticateType.java index 4281c19bba6412..1f16c1f541b391 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/AuthenticateType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/AuthenticateType.java @@ -40,4 +40,22 @@ public static AuthenticateType getAuthTypeConfig() { return DEFAULT; } } + + public static String getAuthTypeConfigString() { + String authType = Config.authentication_type.toLowerCase(); + + if (LdapConfig.ldap_authentication_enabled) { + return LDAP.name(); + } + + switch (authType) { + case "default": + return DEFAULT.toString(); + case "ldap": + return LDAP.toString(); + default: + return authType; + } + } + } diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/AuthenticatorFactory.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/AuthenticatorFactory.java new file mode 100644 index 00000000000000..25ac87de4e7848 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/AuthenticatorFactory.java @@ -0,0 +1,37 @@ +// 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.doris.mysql.authenticate; + +import java.util.Properties; + +public interface AuthenticatorFactory { + /** + * Creates a new instance of Authenticator. + * + * @return an instance of Authenticator + */ + Authenticator create(Properties initProps); + + /** + * Returns the identifier for the factory, such as "ldap" or "default". + * + * @return the factory identifier + */ + String factoryIdentifier(); +} + diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/AuthenticatorManager.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/AuthenticatorManager.java index c00828f82fad92..68b6724b6d808b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/AuthenticatorManager.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/AuthenticatorManager.java @@ -17,47 +17,67 @@ package org.apache.doris.mysql.authenticate; +import org.apache.doris.common.EnvUtils; import org.apache.doris.mysql.MysqlAuthPacket; import org.apache.doris.mysql.MysqlChannel; import org.apache.doris.mysql.MysqlHandshakePacket; import org.apache.doris.mysql.MysqlProto; import org.apache.doris.mysql.MysqlSerializer; -import org.apache.doris.mysql.authenticate.ldap.LdapAuthenticator; import org.apache.doris.mysql.authenticate.password.Password; import org.apache.doris.qe.ConnectContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.Optional; +import java.util.Properties; +import java.util.ServiceLoader; public class AuthenticatorManager { private static final Logger LOG = LogManager.getLogger(AuthenticatorManager.class); - private Authenticator defaultAuthenticator; - private Authenticator authTypeAuthenticator; + private static volatile Authenticator defaultAuthenticator = null; + private static volatile Authenticator authTypeAuthenticator = null; - public AuthenticatorManager(AuthenticateType type) { - LOG.info("authenticate type: {}", type); - this.defaultAuthenticator = new DefaultAuthenticator(); - switch (type) { - case LDAP: - this.authTypeAuthenticator = new LdapAuthenticator(); - break; - case DEFAULT: - default: - this.authTypeAuthenticator = defaultAuthenticator; - break; + public AuthenticatorManager(String type) { + LOG.info("Authenticate type: {}", type); + + if (authTypeAuthenticator == null) { + synchronized (AuthenticatorManager.class) { + if (authTypeAuthenticator == null) { + try { + authTypeAuthenticator = loadFactoriesByName(type); + } catch (Exception e) { + LOG.warn("Failed to load authenticator by name: {}, using default authenticator", type, e); + authTypeAuthenticator = defaultAuthenticator; + } + } + } + } + } + + + private Authenticator loadFactoriesByName(String identifier) throws Exception { + ServiceLoader loader = ServiceLoader.load(AuthenticatorFactory.class); + for (AuthenticatorFactory factory : loader) { + LOG.info("Found Authenticator Plugin Factory: {}", factory.factoryIdentifier()); + if (factory.factoryIdentifier().equalsIgnoreCase(identifier)) { + return factory.create(loadConfigFile()); + } } + throw new RuntimeException("No AuthenticatorFactory found for identifier: " + identifier); } public boolean authenticate(ConnectContext context, - String userName, - MysqlChannel channel, - MysqlSerializer serializer, - MysqlAuthPacket authPacket, - MysqlHandshakePacket handshakePacket) throws IOException { + String userName, + MysqlChannel channel, + MysqlSerializer serializer, + MysqlAuthPacket authPacket, + MysqlHandshakePacket handshakePacket) throws IOException { Authenticator authenticator = chooseAuthenticator(userName); Optional password = authenticator.getPasswordResolver() .resolvePassword(context, channel, serializer, authPacket, handshakePacket); @@ -80,4 +100,15 @@ public boolean authenticate(ConnectContext context, private Authenticator chooseAuthenticator(String userName) { return authTypeAuthenticator.canDeal(userName) ? authTypeAuthenticator : defaultAuthenticator; } + + private static Properties loadConfigFile() throws Exception { + String configFilePath = EnvUtils.getDorisHome() + "/conf/authenticate.conf"; + if (new File(configFilePath).exists()) { + LOG.info("Loading authenticate configuration file: {}", configFilePath); + Properties properties = new Properties(); + properties.load(Files.newInputStream(Paths.get(configFilePath))); + return properties; + } + return new Properties(); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/DefaultAuthenticatorFactory.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/DefaultAuthenticatorFactory.java new file mode 100644 index 00000000000000..5d073a8296a3e4 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/DefaultAuthenticatorFactory.java @@ -0,0 +1,32 @@ +// 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.doris.mysql.authenticate; + +import java.util.Properties; + +public class DefaultAuthenticatorFactory implements AuthenticatorFactory { + @Override + public DefaultAuthenticator create(Properties initProps) { + return new DefaultAuthenticator(); + } + + @Override + public String factoryIdentifier() { + return "default"; + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapAuthenticator.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapAuthenticator.java index e37112372ceb88..cd9cef469d2520 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapAuthenticator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapAuthenticator.java @@ -75,10 +75,11 @@ public boolean canDeal(String qualifiedUser) { if (qualifiedUser.equals(Auth.ROOT_USER) || qualifiedUser.equals(Auth.ADMIN_USER)) { return false; } - if (!Env.getCurrentEnv().getAuth().getLdapManager().doesUserExist(qualifiedUser)) { - return false; - } - return true; + // Fixme Note: LdapManager should be managed internally within the Ldap plugin + // and not be placed inside the Env class. This ensures that Ldap-related + // logic and dependencies are encapsulated within the plugin, promoting + // better modularity and maintainability. + return Env.getCurrentEnv().getAuth().getLdapManager().doesUserExist(qualifiedUser); } /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapAuthenticatorFactory.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapAuthenticatorFactory.java new file mode 100644 index 00000000000000..fba5c350d391de --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapAuthenticatorFactory.java @@ -0,0 +1,37 @@ +// 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.doris.mysql.authenticate.ldap; + +import org.apache.doris.mysql.authenticate.AuthenticatorFactory; + +import java.util.Properties; + +public class LdapAuthenticatorFactory implements AuthenticatorFactory { + + + @Override + public LdapAuthenticator create(Properties initProps) { + return new LdapAuthenticator(); + } + + @Override + public String factoryIdentifier() { + return "ldap"; + } + +} diff --git a/fe/fe-core/src/main/resources/META-INF/services/org.apache.doris.mysql.authenticate.AuthenticatorFactory b/fe/fe-core/src/main/resources/META-INF/services/org.apache.doris.mysql.authenticate.AuthenticatorFactory new file mode 100644 index 00000000000000..3a013ff7f32d53 --- /dev/null +++ b/fe/fe-core/src/main/resources/META-INF/services/org.apache.doris.mysql.authenticate.AuthenticatorFactory @@ -0,0 +1,19 @@ +# +# 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. +# +# +org.apache.doris.mysql.authenticate.DefaultAuthenticatorFactory +org.apache.doris.mysql.authenticate.ldap.LdapAuthenticatorFactory \ No newline at end of file