[OMOperations] Add Reset Password option (#19253)

* Add Reset Password option

* Add Email option

* Add option to set initial password in yaml
This commit is contained in:
Mohit Yadav 2025-01-08 11:51:38 +05:30 committed by GitHub
parent 26bfde8f9c
commit dba3e58e4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 81 additions and 14 deletions

View File

@ -4,7 +4,9 @@ import static org.flywaydb.core.internal.info.MigrationInfoDumper.dumpToAsciiTab
import static org.openmetadata.common.utils.CommonUtil.nullOrEmpty;
import static org.openmetadata.service.Entity.FIELD_OWNERS;
import static org.openmetadata.service.formatter.decorators.MessageDecorator.getDateStringEpochMilli;
import static org.openmetadata.service.jdbi3.UserRepository.AUTH_MECHANISM_FIELD;
import static org.openmetadata.service.util.AsciiTable.printOpenMetadataText;
import static org.openmetadata.service.util.UserUtil.updateUserWithHashedPwd;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
@ -23,6 +25,7 @@ import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@ -41,6 +44,8 @@ import org.openmetadata.schema.ServiceEntityInterface;
import org.openmetadata.schema.entity.app.App;
import org.openmetadata.schema.entity.app.AppRunRecord;
import org.openmetadata.schema.entity.services.ingestionPipelines.IngestionPipeline;
import org.openmetadata.schema.entity.teams.User;
import org.openmetadata.schema.services.connections.metadata.AuthProvider;
import org.openmetadata.schema.settings.Settings;
import org.openmetadata.schema.settings.SettingsType;
import org.openmetadata.schema.system.EventPublisherJob;
@ -60,6 +65,7 @@ import org.openmetadata.service.jdbi3.IngestionPipelineRepository;
import org.openmetadata.service.jdbi3.ListFilter;
import org.openmetadata.service.jdbi3.MigrationDAO;
import org.openmetadata.service.jdbi3.SystemRepository;
import org.openmetadata.service.jdbi3.UserRepository;
import org.openmetadata.service.jdbi3.locator.ConnectionType;
import org.openmetadata.service.migration.api.MigrationWorkflow;
import org.openmetadata.service.resources.CollectionRegistry;
@ -166,13 +172,12 @@ public class OpenMetadataOperations implements Callable<Integer> {
public Integer syncEmailFromEnv() {
try {
parseConfig();
Entity.setCollectionDAO(jdbi.onDemand(CollectionDAO.class));
SystemRepository systemRepository = new SystemRepository();
Settings updatedSettings =
new Settings()
.withConfigType(SettingsType.EMAIL_CONFIGURATION)
.withConfigValue(config.getSmtpSettings());
systemRepository.createOrUpdate(updatedSettings);
Entity.getSystemRepository().createOrUpdate(updatedSettings);
LOG.info("Synced Email Configuration from Environment.");
return 0;
} catch (Exception e) {
LOG.error("Email Sync failed due to ", e);
@ -221,6 +226,58 @@ public class OpenMetadataOperations implements Callable<Integer> {
}
}
@Command(name = "reset-password", description = "Reset the password for a user.")
public Integer resetUserPassword(
@Option(
names = {"-e", "--email"},
description = "Email for which to reset the password.",
required = true)
String email,
@Option(
names = {"-p", "--password"},
description = "Enter user password",
arity = "0..1",
interactive = true,
required = true)
char[] password) {
try {
LOG.info("Resetting password for user : {}", email);
if (nullOrEmpty(password)) {
throw new IllegalArgumentException("Password cannot be empty.");
}
parseConfig();
CollectionRegistry.initialize();
AuthProvider authProvider = config.getAuthenticationConfiguration().getProvider();
// Only Basic Auth provider is supported for password reset
if (!authProvider.equals(AuthProvider.BASIC)) {
LOG.error("Auth Provider is Not Basic. Cannot apply Password");
return 1;
}
UserRepository userRepository = (UserRepository) Entity.getEntityRepository(Entity.USER);
Set<String> fieldList = new HashSet<>(userRepository.getPatchFields().getFieldList());
fieldList.add(AUTH_MECHANISM_FIELD);
User originalUser = userRepository.getByEmail(null, email, new EntityUtil.Fields(fieldList));
// Check if the user is a bot user
if (Boolean.TRUE.equals(originalUser.getIsBot())) {
LOG.error("Bot user : {} cannot have password.", originalUser.getName());
return 1;
}
User updatedUser = JsonUtils.deepCopy(originalUser, User.class);
String inputPwd = new String(password);
updateUserWithHashedPwd(updatedUser, inputPwd);
UserUtil.addOrUpdateUser(updatedUser);
LOG.info("Password updated successfully.");
return 0;
} catch (Exception e) {
LOG.error("Failed to reset user password.", e);
return 1;
}
}
@Command(
name = "migrate",
description = "Migrates the OpenMetadata database schema and search index mappings.")
@ -652,6 +709,7 @@ public class OpenMetadataOperations implements Callable<Integer> {
collectionDAO = jdbi.onDemand(CollectionDAO.class);
Entity.setSearchRepository(searchRepository);
Entity.setCollectionDAO(collectionDAO);
Entity.setSystemRepository(new SystemRepository());
Entity.initializeRepositories(config, jdbi);
}

View File

@ -19,6 +19,7 @@ import static org.openmetadata.schema.entity.teams.AuthenticationMechanism.AuthT
import static org.openmetadata.schema.type.Include.NON_DELETED;
import static org.openmetadata.service.Entity.ADMIN_ROLE;
import static org.openmetadata.service.Entity.ADMIN_USER_NAME;
import static org.openmetadata.service.jdbi3.UserRepository.AUTH_MECHANISM_FIELD;
import at.favre.lib.crypto.bcrypt.BCrypt;
import java.util.ArrayList;
@ -62,8 +63,18 @@ public final class UserUtil {
public static void addUsers(
AuthProvider authProvider, Set<String> adminUsers, String domain, Boolean isAdmin) {
try {
for (String username : adminUsers) {
createOrUpdateUser(authProvider, username, domain, isAdmin);
for (String keyValue : adminUsers) {
String userName = "";
String password = "";
if (keyValue.contains(":")) {
String[] keyValueArray = keyValue.split(":");
userName = keyValueArray[0];
password = keyValueArray[1];
} else {
userName = keyValue;
password = getPassword(userName);
}
createOrUpdateUser(authProvider, userName, password, domain, isAdmin);
}
} catch (Exception ex) {
LOG.error("[BootstrapUser] Encountered Exception while bootstrapping admin user", ex);
@ -71,27 +82,26 @@ public final class UserUtil {
}
private static void createOrUpdateUser(
AuthProvider authProvider, String username, String domain, Boolean isAdmin) {
AuthProvider authProvider, String username, String password, String domain, Boolean isAdmin) {
UserRepository userRepository = (UserRepository) Entity.getEntityRepository(Entity.USER);
User updatedUser = null;
try {
// Create Required Fields List
Set<String> fieldList = new HashSet<>(userRepository.getPatchFields().getFieldList());
fieldList.add("authenticationMechanism");
fieldList.add(AUTH_MECHANISM_FIELD);
// Fetch Original User, is available
User originalUser = userRepository.getByName(null, username, new Fields(fieldList));
if (Boolean.FALSE.equals(originalUser.getIsBot())
&& Boolean.FALSE.equals(originalUser.getIsAdmin())) {
&& Boolean.TRUE.equals(originalUser.getIsAdmin())) {
updatedUser = originalUser;
// Update Auth Mechanism if not present, and send mail to the user
if (authProvider.equals(AuthProvider.BASIC)) {
if (originalUser.getAuthenticationMechanism() == null
|| originalUser.getAuthenticationMechanism().equals(new AuthenticationMechanism())) {
String randomPwd = getPassword(username);
updateUserWithHashedPwd(updatedUser, randomPwd);
EmailUtil.sendInviteMailToAdmin(updatedUser, randomPwd);
updateUserWithHashedPwd(updatedUser, password);
EmailUtil.sendInviteMailToAdmin(updatedUser, password);
}
} else {
updatedUser.setAuthenticationMechanism(new AuthenticationMechanism());
@ -114,9 +124,8 @@ public final class UserUtil {
updatedUser = user(username, domain, username).withIsAdmin(isAdmin).withIsEmailVerified(true);
// Update Auth Mechanism if not present, and send mail to the user
if (authProvider.equals(AuthProvider.BASIC)) {
String randomPwd = getPassword(username);
updateUserWithHashedPwd(updatedUser, randomPwd);
EmailUtil.sendInviteMailToAdmin(updatedUser, randomPwd);
updateUserWithHashedPwd(updatedUser, password);
EmailUtil.sendInviteMailToAdmin(updatedUser, password);
}
}