[FIX] ldap User Name (#17764)

* migrate userName to emailPrefix for ldap auth provider.

* migrate userName to emailPrefix for ldap auth provider.

* fix migration.

* move migration to v155

* Update Ldap Authenticator

* Fix Ldap Issue on Login

---------

Co-authored-by: Mohit Yadav <105265192+mohityadav766@users.noreply.github.com>
Co-authored-by: mohitdeuex <mohit.y@deuexsolutions.com>
This commit is contained in:
Siddhant 2024-09-23 11:35:20 +05:30 committed by GitHub
parent c1e20873b1
commit bc3d4c778e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 226 additions and 63 deletions

View File

@ -454,6 +454,7 @@ public class OpenMetadataApplication extends Application<OpenMetadataApplication
connectionType,
conf.getMigrationConfiguration().getExtensionPath(),
conf.getPipelineServiceClientConfiguration(),
conf.getAuthenticationConfiguration(),
false);
migrationWorkflow.loadMigrations();
migrationWorkflow.validateMigrationsForServer();

View File

@ -9,6 +9,7 @@ import java.util.Map;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.jdbi.v3.core.Handle;
import org.openmetadata.schema.api.security.AuthenticationConfiguration;
import org.openmetadata.sdk.PipelineServiceClientInterface;
import org.openmetadata.service.clients.pipeline.PipelineServiceClientFactory;
import org.openmetadata.service.jdbi3.CollectionDAO;
@ -24,6 +25,7 @@ public class MigrationProcessImpl implements MigrationProcess {
protected CollectionDAO collectionDAO;
protected Handle handle;
protected PipelineServiceClientInterface pipelineServiceClient;
protected AuthenticationConfiguration authenticationConfiguration;
private final MigrationFile migrationFile;
public @Getter MigrationContext context;
@ -40,6 +42,7 @@ public class MigrationProcessImpl implements MigrationProcess {
this.pipelineServiceClient =
PipelineServiceClientFactory.createPipelineServiceClient(
this.migrationFile.pipelineServiceClientConfiguration);
this.authenticationConfiguration = migrationFile.authenticationConfiguration;
}
@Override

View File

@ -18,6 +18,7 @@ import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.Jdbi;
import org.json.JSONObject;
import org.openmetadata.schema.api.configuration.pipelineServiceClient.PipelineServiceClientConfiguration;
import org.openmetadata.schema.api.security.AuthenticationConfiguration;
import org.openmetadata.service.jdbi3.MigrationDAO;
import org.openmetadata.service.jdbi3.locator.ConnectionType;
import org.openmetadata.service.migration.QueryStatus;
@ -35,6 +36,7 @@ public class MigrationWorkflow {
private final ConnectionType connectionType;
private final String extensionSQLScriptRootPath;
@Getter private final PipelineServiceClientConfiguration pipelineServiceClientConfiguration;
@Getter private final AuthenticationConfiguration authenticationConfiguration;
private final MigrationDAO migrationDAO;
private final Jdbi jdbi;
private final boolean forceMigrations;
@ -47,6 +49,7 @@ public class MigrationWorkflow {
ConnectionType connectionType,
String extensionSQLScriptRootPath,
PipelineServiceClientConfiguration pipelineServiceClientConfiguration,
AuthenticationConfiguration authenticationConfiguration,
boolean forceMigrations) {
this.jdbi = jdbi;
this.migrationDAO = jdbi.onDemand(MigrationDAO.class);
@ -55,6 +58,7 @@ public class MigrationWorkflow {
this.connectionType = connectionType;
this.extensionSQLScriptRootPath = extensionSQLScriptRootPath;
this.pipelineServiceClientConfiguration = pipelineServiceClientConfiguration;
this.authenticationConfiguration = authenticationConfiguration;
}
public void loadMigrations() {
@ -64,7 +68,8 @@ public class MigrationWorkflow {
nativeSQLScriptRootPath,
connectionType,
extensionSQLScriptRootPath,
pipelineServiceClientConfiguration);
pipelineServiceClientConfiguration,
authenticationConfiguration);
// Filter Migrations to Be Run
this.migrations = filterAndGetMigrationsToRun(availableMigrations);
}
@ -83,10 +88,15 @@ public class MigrationWorkflow {
String nativeSQLScriptRootPath,
ConnectionType connectionType,
String extensionSQLScriptRootPath,
PipelineServiceClientConfiguration pipelineServiceClientConfiguration) {
PipelineServiceClientConfiguration pipelineServiceClientConfiguration,
AuthenticationConfiguration authenticationConfiguration) {
List<MigrationFile> availableOMNativeMigrations =
getMigrationFilesFromPath(
nativeSQLScriptRootPath, connectionType, pipelineServiceClientConfiguration, false);
nativeSQLScriptRootPath,
connectionType,
pipelineServiceClientConfiguration,
authenticationConfiguration,
false);
// If we only have OM migrations, return them
if (extensionSQLScriptRootPath == null || extensionSQLScriptRootPath.isEmpty()) {
@ -96,7 +106,11 @@ public class MigrationWorkflow {
// Otherwise, fetch the extension migrations and sort the executions
List<MigrationFile> availableExtensionMigrations =
getMigrationFilesFromPath(
extensionSQLScriptRootPath, connectionType, pipelineServiceClientConfiguration, true);
extensionSQLScriptRootPath,
connectionType,
pipelineServiceClientConfiguration,
authenticationConfiguration,
true);
/*
If we create migrations version as:
@ -114,6 +128,7 @@ public class MigrationWorkflow {
String path,
ConnectionType connectionType,
PipelineServiceClientConfiguration pipelineServiceClientConfiguration,
AuthenticationConfiguration authenticationConfiguration,
Boolean isExtension) {
return Arrays.stream(Objects.requireNonNull(new File(path).listFiles(File::isDirectory)))
.map(
@ -123,6 +138,7 @@ public class MigrationWorkflow {
migrationDAO,
connectionType,
pipelineServiceClientConfiguration,
authenticationConfiguration,
isExtension))
.sorted()
.toList();

View File

@ -0,0 +1,21 @@
package org.openmetadata.service.migration.mysql.v155;
import static org.openmetadata.service.migration.utils.v155.MigrationUtil.updateUserNameToEmailPrefixForLdapAuthProvider;
import lombok.SneakyThrows;
import org.openmetadata.service.migration.api.MigrationProcessImpl;
import org.openmetadata.service.migration.utils.MigrationFile;
public class Migration extends MigrationProcessImpl {
public Migration(MigrationFile migrationFile) {
super(migrationFile);
}
@Override
@SneakyThrows
public void runDataMigration() {
updateUserNameToEmailPrefixForLdapAuthProvider(
handle, collectionDAO, authenticationConfiguration, false);
}
}

View File

@ -0,0 +1,21 @@
package org.openmetadata.service.migration.postgres.v155;
import static org.openmetadata.service.migration.utils.v155.MigrationUtil.updateUserNameToEmailPrefixForLdapAuthProvider;
import lombok.SneakyThrows;
import org.openmetadata.service.migration.api.MigrationProcessImpl;
import org.openmetadata.service.migration.utils.MigrationFile;
public class Migration extends MigrationProcessImpl {
public Migration(MigrationFile migrationFile) {
super(migrationFile);
}
@Override
@SneakyThrows
public void runDataMigration() {
updateUserNameToEmailPrefixForLdapAuthProvider(
handle, collectionDAO, authenticationConfiguration, true);
}
}

View File

@ -14,6 +14,7 @@ import org.flywaydb.core.internal.resource.filesystem.FileSystemResource;
import org.flywaydb.core.internal.sqlscript.SqlStatementIterator;
import org.flywaydb.database.mysql.MySQLParser;
import org.openmetadata.schema.api.configuration.pipelineServiceClient.PipelineServiceClientConfiguration;
import org.openmetadata.schema.api.security.AuthenticationConfiguration;
import org.openmetadata.service.jdbi3.MigrationDAO;
import org.openmetadata.service.jdbi3.locator.ConnectionType;
import org.openmetadata.service.util.EntityUtil;
@ -23,6 +24,8 @@ public class MigrationFile implements Comparable<MigrationFile> {
public final String version;
public final ConnectionType connectionType;
public final PipelineServiceClientConfiguration pipelineServiceClientConfiguration;
public final AuthenticationConfiguration authenticationConfiguration;
public final File dir;
public final Boolean isExtension;
public final String dbPackageName;
@ -38,6 +41,7 @@ public class MigrationFile implements Comparable<MigrationFile> {
MigrationDAO migrationDAO,
ConnectionType connectionType,
PipelineServiceClientConfiguration pipelineServiceClientConfiguration,
AuthenticationConfiguration authenticationConfiguration,
Boolean isExtension) {
this.dir = dir;
this.isExtension = isExtension;
@ -45,6 +49,7 @@ public class MigrationFile implements Comparable<MigrationFile> {
this.connectionType = connectionType;
this.migrationDAO = migrationDAO;
this.pipelineServiceClientConfiguration = pipelineServiceClientConfiguration;
this.authenticationConfiguration = authenticationConfiguration;
this.dbPackageName = connectionType == ConnectionType.MYSQL ? "mysql" : "postgres";
versionNumbers = convertToNumber(version);
schemaChanges = new ArrayList<>();

View File

@ -0,0 +1,60 @@
package org.openmetadata.service.migration.utils.v155;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.jdbi.v3.core.Handle;
import org.openmetadata.schema.api.security.AuthenticationConfiguration;
import org.openmetadata.schema.entity.teams.User;
import org.openmetadata.schema.services.connections.metadata.AuthProvider;
import org.openmetadata.schema.utils.EntityInterfaceUtil;
import org.openmetadata.service.jdbi3.CollectionDAO;
import org.openmetadata.service.util.JsonUtils;
@Slf4j
public class MigrationUtil {
public static void updateUserNameToEmailPrefixForLdapAuthProvider(
Handle handle,
CollectionDAO daoCollection,
AuthenticationConfiguration config,
boolean postgres) {
if (config.getProvider().equals(AuthProvider.LDAP)) {
LOG.info("Starting migration username -> email prefix");
int total = daoCollection.userDAO().listTotalCount();
int offset = 0;
int limit = 200;
while (offset < total) {
List<String> userEntities = daoCollection.userDAO().listAfterWithOffset(limit, offset);
for (String json : userEntities) {
User userEntity = JsonUtils.readValue(json, User.class);
String email = userEntity.getEmail();
String emailPrefix = email.substring(0, email.indexOf("@"));
userEntity.setFullyQualifiedName(EntityInterfaceUtil.quoteName(emailPrefix));
userEntity.setName(emailPrefix);
daoCollection.userDAO().update(userEntity);
}
offset = offset + limit;
}
updateUserEntityNameHash(handle, postgres);
LOG.info("Completed migrating username -> email prefix");
}
}
public static void updateUserEntityNameHash(Handle handle, boolean postgres) {
String updateNameHashSql;
if (postgres) {
updateNameHashSql = "UPDATE user_entity SET nameHash = MD5(json ->> 'fullyQualifiedName');";
} else {
updateNameHashSql =
"UPDATE user_entity SET nameHash = MD5(JSON_UNQUOTE(JSON_EXTRACT(json, '$.fullyQualifiedName')));";
}
try {
handle.execute(updateNameHashSql);
LOG.info("Successfully updated nameHash for all user entities.");
} catch (Exception e) {
LOG.error("Error updating nameHash field", e);
}
}
}

View File

@ -33,13 +33,13 @@ public interface AuthenticatorHandler {
void checkIfLoginBlocked(String userName);
void recordFailedLoginAttempt(String providedIdentity, User user)
void recordFailedLoginAttempt(String email, String userName)
throws TemplateException, IOException;
void validatePassword(String providedIdentity, User storedUser, String reqPassword)
void validatePassword(String providedIdentity, String reqPassword, User omUser)
throws TemplateException, IOException;
User lookUserInProvider(String userName);
User lookUserInProvider(String email, String pwd) throws TemplateException, IOException;
default User registerUser(RegistrationRequest registrationRequest) {
throw new CustomExceptionMessage(

View File

@ -261,7 +261,8 @@ public class BasicAuthenticator implements AuthenticatorHandler {
// Update user about Password Change
try {
sendAccountStatus(storedUser, "Update Password", "Change Successful");
sendAccountStatus(
storedUser.getName(), storedUser.getEmail(), "Update Password", "Change Successful");
} catch (TemplateException ex) {
LOG.error("Error in sending Password Change Mail to User. Reason : " + ex.getMessage(), ex);
throw new CustomExceptionMessage(424, FAILED_SEND_EMAIL, EMAIL_SENDING_ISSUE);
@ -466,28 +467,29 @@ public class BasicAuthenticator implements AuthenticatorHandler {
@Override
public JwtResponse loginUser(LoginRequest loginRequest) throws IOException, TemplateException {
String userName = loginRequest.getEmail();
checkIfLoginBlocked(userName);
User storedUser = lookUserInProvider(userName);
validatePassword(userName, storedUser, loginRequest.getPassword());
String email = loginRequest.getEmail();
checkIfLoginBlocked(email);
User storedUser = lookUserInProvider(email, loginRequest.getPassword());
validatePassword(email, loginRequest.getPassword(), storedUser);
return getJwtResponse(storedUser, SecurityUtil.getLoginConfiguration().getJwtTokenExpiryTime());
}
@Override
public void checkIfLoginBlocked(String userName) {
if (loginAttemptCache.isLoginBlocked(userName)) {
public void checkIfLoginBlocked(String email) {
if (loginAttemptCache.isLoginBlocked(email)) {
throw new AuthenticationException(MAX_FAILED_LOGIN_ATTEMPT);
}
}
@Override
public void recordFailedLoginAttempt(String providedIdentity, User storedUser)
public void recordFailedLoginAttempt(String email, String userName)
throws TemplateException, IOException {
loginAttemptCache.recordFailedLogin(providedIdentity);
int failedLoginAttempt = loginAttemptCache.getUserFailedLoginCount(providedIdentity);
loginAttemptCache.recordFailedLogin(email);
int failedLoginAttempt = loginAttemptCache.getUserFailedLoginCount(email);
if (failedLoginAttempt == SecurityUtil.getLoginConfiguration().getMaxLoginFailAttempts()) {
sendAccountStatus(
storedUser,
userName,
email,
"Multiple Failed Login Attempts.",
String.format(
"Someone is trying to access your account. Login is Blocked for %s minutes. Please change your password.",
@ -495,35 +497,35 @@ public class BasicAuthenticator implements AuthenticatorHandler {
}
}
public void validatePassword(String providedIdentity, User storedUser, String reqPassword)
public void validatePassword(String providedIdentity, String reqPassword, User omUser)
throws TemplateException, IOException {
// when basic auth is enabled and the user is created through the API without password, the
// stored auth mechanism
// for the user is null
if (storedUser.getAuthenticationMechanism() == null) {
if (omUser.getAuthenticationMechanism() == null) {
throw new AuthenticationException(INVALID_USERNAME_PASSWORD);
}
@SuppressWarnings("unchecked")
LinkedHashMap<String, String> storedData =
(LinkedHashMap<String, String>) storedUser.getAuthenticationMechanism().getConfig();
(LinkedHashMap<String, String>) omUser.getAuthenticationMechanism().getConfig();
String storedHashPassword = storedData.get("password");
if (!BCrypt.verifyer().verify(reqPassword.toCharArray(), storedHashPassword).verified) {
// record Failed Login Attempts
recordFailedLoginAttempt(providedIdentity, storedUser);
recordFailedLoginAttempt(omUser.getEmail(), omUser.getName());
throw new AuthenticationException(INVALID_USERNAME_PASSWORD);
}
}
@Override
public User lookUserInProvider(String userName) {
public User lookUserInProvider(String email, String pwd) {
User storedUser = null;
try {
if (userName.contains("@")) {
if (email.contains("@")) {
// lookup by User Email
storedUser =
userRepository.getByEmail(
null,
userName,
email,
new EntityUtil.Fields(
Set.of(USER_PROTECTED_FIELDS, "roles"), "authenticationMechanism,roles"));
}

View File

@ -12,6 +12,8 @@ import static org.openmetadata.service.exception.CatalogExceptionMessage.LDAP_MI
import static org.openmetadata.service.exception.CatalogExceptionMessage.MAX_FAILED_LOGIN_ATTEMPT;
import static org.openmetadata.service.exception.CatalogExceptionMessage.MULTIPLE_EMAIL_ENTRIES;
import static org.openmetadata.service.exception.CatalogExceptionMessage.PASSWORD_RESET_TOKEN_EXPIRED;
import static org.openmetadata.service.exception.CatalogExceptionMessage.SELF_SIGNUP_DISABLED_MESSAGE;
import static org.openmetadata.service.exception.CatalogExceptionMessage.SELF_SIGNUP_NOT_ENABLED;
import static org.openmetadata.service.util.UserUtil.getRoleListFromUser;
import com.fasterxml.jackson.core.JsonProcessingException;
@ -85,6 +87,7 @@ public class LdapAuthenticator implements AuthenticatorHandler {
private LoginAttemptCache loginAttemptCache;
private LdapConfiguration ldapConfiguration;
private LDAPConnectionPool ldapLookupConnectionPool;
private boolean isSelfSignUpEnabled;
@Override
public void init(OpenMetadataApplicationConfig config) {
@ -100,6 +103,7 @@ public class LdapAuthenticator implements AuthenticatorHandler {
this.tokenRepository = Entity.getTokenRepository();
this.ldapConfiguration = config.getAuthenticationConfiguration().getLdapConfiguration();
this.loginAttemptCache = new LoginAttemptCache();
this.isSelfSignUpEnabled = config.getAuthenticationConfiguration().getEnableSelfSignup();
}
private LDAPConnectionPool getLdapConnectionPool(LdapConfiguration ldapConfiguration) {
@ -138,10 +142,9 @@ public class LdapAuthenticator implements AuthenticatorHandler {
@Override
public JwtResponse loginUser(LoginRequest loginRequest) throws IOException, TemplateException {
checkIfLoginBlocked(loginRequest.getEmail());
User storedUser = lookUserInProvider(loginRequest.getEmail());
validatePassword(storedUser.getEmail(), storedUser, loginRequest.getPassword());
User omUser = checkAndCreateUser(storedUser.getEmail(), storedUser.getName());
String email = loginRequest.getEmail();
checkIfLoginBlocked(email);
User omUser = lookUserInProvider(email, loginRequest.getPassword());
return getJwtResponse(omUser, SecurityUtil.getLoginConfiguration().getJwtTokenExpiryTime());
}
@ -149,21 +152,25 @@ public class LdapAuthenticator implements AuthenticatorHandler {
* Check if the user exists in database by userName, if user exist, reassign roles for user according to it's ldap
* group else, create a new user and assign roles according to it's ldap group
*
* @param email email address of user
* @param name userName of user
* @param userDn userDn from LDAP
* @param email Email of the User
* @return user info
* @author Eric Wen@2023-07-16 17:06:43
*/
private User checkAndCreateUser(String email, String name) throws IOException {
private User checkAndCreateUser(String userDn, String email, String userName) throws IOException {
// Check if the user exists in OM Database
try {
User omUser =
userRepository.getByName(null, name, userRepository.getFields("id,name,email,roles"));
getRoleForLdap(omUser, Boolean.TRUE);
userRepository.getByEmail(null, email, userRepository.getFields("id,name,email,roles"));
getRoleForLdap(userDn, omUser, Boolean.TRUE);
return omUser;
} catch (EntityNotFoundException ex) {
// User does not exist
return userRepository.create(null, getUserForLdap(email, name));
if (isSelfSignUpEnabled) {
return userRepository.create(null, getUserForLdap(userDn, email, userName));
} else {
throw new CustomExceptionMessage(
INTERNAL_SERVER_ERROR, SELF_SIGNUP_NOT_ENABLED, SELF_SIGNUP_DISABLED_MESSAGE);
}
}
}
@ -175,13 +182,14 @@ public class LdapAuthenticator implements AuthenticatorHandler {
}
@Override
public void recordFailedLoginAttempt(String providedIdentity, User storedUser)
public void recordFailedLoginAttempt(String email, String userName)
throws TemplateException, IOException {
loginAttemptCache.recordFailedLogin(providedIdentity);
int failedLoginAttempt = loginAttemptCache.getUserFailedLoginCount(providedIdentity);
loginAttemptCache.recordFailedLogin(email);
int failedLoginAttempt = loginAttemptCache.getUserFailedLoginCount(email);
if (failedLoginAttempt == SecurityUtil.getLoginConfiguration().getMaxLoginFailAttempts()) {
EmailUtil.sendAccountStatus(
storedUser,
userName,
email,
"Multiple Failed Login Attempts.",
String.format(
"Someone is tried accessing your account. Login is Blocked for %s seconds.",
@ -190,12 +198,12 @@ public class LdapAuthenticator implements AuthenticatorHandler {
}
@Override
public void validatePassword(String providedIdentity, User storedUser, String reqPassword)
public void validatePassword(String userDn, String reqPassword, User dummy)
throws TemplateException, IOException {
// performed in LDAP , the storedUser's name set as DN of the User in Ldap
BindResult bindingResult = null;
try {
bindingResult = ldapLookupConnectionPool.bind(storedUser.getName(), reqPassword);
bindingResult = ldapLookupConnectionPool.bind(userDn, reqPassword);
if (Objects.equals(bindingResult.getResultCode().getName(), ResultCode.SUCCESS.getName())) {
return;
}
@ -203,7 +211,7 @@ public class LdapAuthenticator implements AuthenticatorHandler {
if (bindingResult != null
&& Objects.equals(
bindingResult.getResultCode().getName(), ResultCode.INVALID_CREDENTIALS.getName())) {
recordFailedLoginAttempt(providedIdentity, storedUser);
recordFailedLoginAttempt(dummy.getEmail(), dummy.getName());
throw new CustomExceptionMessage(
UNAUTHORIZED, INVALID_USER_OR_PASSWORD, INVALID_EMAIL_PASSWORD);
}
@ -218,7 +226,20 @@ public class LdapAuthenticator implements AuthenticatorHandler {
}
@Override
public User lookUserInProvider(String email) {
public User lookUserInProvider(String email, String pwd) throws TemplateException, IOException {
String userDN = getUserDnFromLdap(email);
if (!nullOrEmpty(userDN)) {
User dummy = getUserForLdap(email);
validatePassword(userDN, pwd, dummy);
return checkAndCreateUser(userDN, email, dummy.getName());
}
throw new CustomExceptionMessage(
INTERNAL_SERVER_ERROR, INVALID_USER_OR_PASSWORD, INVALID_EMAIL_PASSWORD);
}
private String getUserDnFromLdap(String email) {
try {
Filter emailFilter =
Filter.createEqualityFilter(ldapConfiguration.getMailAttributeName(), email);
@ -237,8 +258,10 @@ public class LdapAuthenticator implements AuthenticatorHandler {
Attribute emailAttr =
searchResultEntry.getAttribute(ldapConfiguration.getMailAttributeName());
if (!CommonUtil.nullOrEmpty(userDN) && emailAttr != null) {
return getUserForLdap(email).withName(userDN.toLowerCase());
if (!CommonUtil.nullOrEmpty(userDN)
&& emailAttr != null
&& email.equalsIgnoreCase(emailAttr.getValue())) {
return userDN;
} else {
throw new CustomExceptionMessage(FORBIDDEN, INVALID_USER_OR_PASSWORD, LDAP_MISSING_ATTR);
}
@ -247,7 +270,7 @@ public class LdapAuthenticator implements AuthenticatorHandler {
INTERNAL_SERVER_ERROR, MULTIPLE_EMAIL_ENTRIES, MULTIPLE_EMAIL_ENTRIES);
} else {
throw new CustomExceptionMessage(
INTERNAL_SERVER_ERROR, MULTIPLE_EMAIL_ENTRIES, INVALID_EMAIL_PASSWORD);
INTERNAL_SERVER_ERROR, INVALID_USER_OR_PASSWORD, INVALID_EMAIL_PASSWORD);
}
} catch (LDAPException ex) {
throw new CustomExceptionMessage(INTERNAL_SERVER_ERROR, "LDAP_ERROR", ex.getMessage());
@ -262,14 +285,14 @@ public class LdapAuthenticator implements AuthenticatorHandler {
.withAuthenticationMechanism(null);
}
private User getUserForLdap(String email, String userName) {
private User getUserForLdap(String ldapUserDn, String email, String userName) {
User user =
UserUtil.getUser(
userName, new CreateUser().withName(userName).withEmail(email).withIsBot(false))
.withIsEmailVerified(false)
.withAuthenticationMechanism(null);
try {
getRoleForLdap(user, false);
getRoleForLdap(ldapUserDn, user, false);
} catch (JsonProcessingException e) {
LOG.error(
"Failed to assign roles from LDAP to OpenMetadata for the user {} due to {}",
@ -286,7 +309,8 @@ public class LdapAuthenticator implements AuthenticatorHandler {
* @param reAssign flag to decide whether to reassign roles
* @author Eric Wen@2023-07-16 17:23:57
*/
private void getRoleForLdap(User user, Boolean reAssign) throws JsonProcessingException {
private void getRoleForLdap(String userDn, User user, Boolean reAssign)
throws JsonProcessingException {
// Get user's groups from LDAP server using the DN of the user
try {
Filter groupFilter =
@ -294,8 +318,7 @@ public class LdapAuthenticator implements AuthenticatorHandler {
ldapConfiguration.getGroupAttributeName(),
ldapConfiguration.getGroupAttributeValue());
Filter groupMemberAttr =
Filter.createEqualityFilter(
ldapConfiguration.getGroupMemberAttributeName(), user.getName());
Filter.createEqualityFilter(ldapConfiguration.getGroupMemberAttributeName(), userDn);
Filter groupAndMemberFilter = Filter.createANDFilter(groupFilter, groupMemberAttr);
SearchRequest searchRequest =
new SearchRequest(

View File

@ -33,7 +33,7 @@ public class NoopAuthenticator implements AuthenticatorHandler {
}
@Override
public void recordFailedLoginAttempt(String providedIdentity, User user) {
public void recordFailedLoginAttempt(String providedIdentity, String userName) {
throw new CustomExceptionMessage(
Response.Status.FORBIDDEN,
AUTHENTICATOR_OPERATION_NOT_SUPPORTED,
@ -41,7 +41,7 @@ public class NoopAuthenticator implements AuthenticatorHandler {
}
@Override
public void validatePassword(String providedIdentity, User storedUser, String reqPassword) {
public void validatePassword(String providedIdentity, String reqPassword, User storedUser) {
throw new CustomExceptionMessage(
Response.Status.FORBIDDEN,
AUTHENTICATOR_OPERATION_NOT_SUPPORTED,
@ -49,7 +49,7 @@ public class NoopAuthenticator implements AuthenticatorHandler {
}
@Override
public User lookUserInProvider(String userName) {
public User lookUserInProvider(String email, String pwd) {
throw new CustomExceptionMessage(
Response.Status.FORBIDDEN,
AUTHENTICATOR_OPERATION_NOT_SUPPORTED,

View File

@ -618,6 +618,7 @@ public class OpenMetadataOperations implements Callable<Integer> {
connType,
extensionSQLScriptRootPath,
config.getPipelineServiceClientConfiguration(),
config.getAuthenticationConfiguration(),
force);
workflow.loadMigrations();
workflow.printMigrationInfo();

View File

@ -121,7 +121,7 @@ public class EmailUtil {
return null;
}
public static void sendAccountStatus(User user, String action, String status)
public static void sendAccountStatus(String userName, String email, String action, String status)
throws IOException, TemplateException {
if (Boolean.TRUE.equals(getSmtpSettings().getEnableSmtpServer())) {
@ -129,7 +129,7 @@ public class EmailUtil {
new TemplatePopulatorBuilder()
.add(ENTITY, getSmtpSettings().getEmailingEntity())
.add(SUPPORT_URL, getSmtpSettings().getSupportUrl())
.add(USERNAME, user.getName())
.add(USERNAME, userName)
.add(ACTION_KEY, action)
.add(ACTION_STATUS_KEY, status)
.build();
@ -137,11 +137,11 @@ public class EmailUtil {
sendMail(
getAccountStatusChangeSubject(),
templatePopulator,
user.getEmail(),
email,
ACCOUNT_ACTIVITY_CHANGE_TEMPLATE,
true);
} else {
LOG.warn(EMAIL_IGNORE_MSG, user.getEmail());
LOG.warn(EMAIL_IGNORE_MSG, userName);
}
}

View File

@ -48,6 +48,7 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInstance;
import org.openmetadata.common.utils.CommonUtil;
import org.openmetadata.schema.api.configuration.pipelineServiceClient.PipelineServiceClientConfiguration;
import org.openmetadata.schema.api.security.AuthenticationConfiguration;
import org.openmetadata.schema.service.configuration.elasticsearch.ElasticSearchConfiguration;
import org.openmetadata.schema.type.IndexMappingLanguage;
import org.openmetadata.service.jdbi3.CollectionDAO;
@ -208,6 +209,7 @@ public abstract class OpenMetadataApplicationTest {
nativeMigrationScriptsLocation,
extensionMigrationScripsLocation,
null,
null,
false);
createIndices();
APP.before();
@ -221,6 +223,7 @@ public abstract class OpenMetadataApplicationTest {
String nativeMigrationSQLPath,
String extensionSQLScriptRootPath,
PipelineServiceClientConfiguration pipelineServiceClientConfiguration,
AuthenticationConfiguration authenticationConfiguration,
boolean forceMigrations) {
DatasourceConfig.initialize(connType.label);
MigrationWorkflow workflow =
@ -230,6 +233,7 @@ public abstract class OpenMetadataApplicationTest {
connType,
extensionSQLScriptRootPath,
pipelineServiceClientConfiguration,
authenticationConfiguration,
forceMigrations);
// Initialize search repository
SearchRepository searchRepository =

View File

@ -28,7 +28,7 @@ public class MigrationWorkflowTest extends OpenMetadataApplicationTest {
migrationWorkflow =
spy(
new MigrationWorkflow(
jdbi, "nativePath", ConnectionType.MYSQL, "extensionPath", null, false));
jdbi, "nativePath", ConnectionType.MYSQL, "extensionPath", null, null, false));
omMigrationList =
List.of(
@ -37,18 +37,21 @@ public class MigrationWorkflowTest extends OpenMetadataApplicationTest {
null,
ConnectionType.MYSQL,
migrationWorkflow.getPipelineServiceClientConfiguration(),
migrationWorkflow.getAuthenticationConfiguration(),
false),
new MigrationFile(
new File("/bootstrap/sql/migrations/native/1.2.0"),
null,
ConnectionType.MYSQL,
migrationWorkflow.getPipelineServiceClientConfiguration(),
migrationWorkflow.getAuthenticationConfiguration(),
false),
new MigrationFile(
new File("/bootstrap/sql/migrations/native/1.2.1"),
null,
ConnectionType.MYSQL,
migrationWorkflow.getPipelineServiceClientConfiguration(),
migrationWorkflow.getAuthenticationConfiguration(),
false));
collateMigrationList =
@ -58,12 +61,14 @@ public class MigrationWorkflowTest extends OpenMetadataApplicationTest {
null,
ConnectionType.MYSQL,
migrationWorkflow.getPipelineServiceClientConfiguration(),
migrationWorkflow.getAuthenticationConfiguration(),
true),
new MigrationFile(
new File("/bootstrap-collate/sql/migrations/native/1.2.2-collate"),
null,
ConnectionType.MYSQL,
migrationWorkflow.getPipelineServiceClientConfiguration(),
migrationWorkflow.getAuthenticationConfiguration(),
true));
}
@ -72,18 +77,19 @@ public class MigrationWorkflowTest extends OpenMetadataApplicationTest {
Mockito.doReturn(omMigrationList)
.when(migrationWorkflow)
.getMigrationFilesFromPath(
eq("nativePath"), any(ConnectionType.class), eq(null), eq(false));
eq("nativePath"), any(ConnectionType.class), eq(null), eq(null), eq(false));
Mockito.doReturn(collateMigrationList)
.when(migrationWorkflow)
.getMigrationFilesFromPath(
eq("extensionPath"), any(ConnectionType.class), eq(null), eq(true));
eq("extensionPath"), any(ConnectionType.class), eq(null), eq(null), eq(true));
List<MigrationFile> foundList =
migrationWorkflow.getMigrationFiles(
"nativePath",
ConnectionType.MYSQL,
"extensionPath",
migrationWorkflow.getPipelineServiceClientConfiguration());
migrationWorkflow.getPipelineServiceClientConfiguration(),
migrationWorkflow.getAuthenticationConfiguration());
assertEquals(
List.of("1.1.0", "1.1.0-collate", "1.2.0", "1.2.1", "1.2.2-collate"),