diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserGroup.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserGroup.java index 47af8ef6ced260f0d5c8422b3d2972f17f287268..704e204abe092da1d9271ca722aea4e783aaab9c 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserGroup.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserGroup.java @@ -27,6 +27,8 @@ public class UserGroup private boolean enabled = true; private List<String> ldapGroupKeys; + + private List<String> users; private List<String> admins; @@ -72,6 +74,11 @@ public class UserGroup return ldapGroupKeys; } + public List<String> getUsers() + { + return users; + } + public List<String> getShareIds() { return shareIds; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserManagementMaintenanceTask.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserManagementMaintenanceTask.java index 111d4cd6cd46ae73e9b08be69ef8e9543ba903f5..f2a4ae2bd2d6d5b3a125d912da98f0e81c6a8501 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserManagementMaintenanceTask.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserManagementMaintenanceTask.java @@ -30,6 +30,7 @@ import ch.systemsx.cisd.authentication.ldap.LDAPAuthenticationService; import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; import ch.systemsx.cisd.common.filesystem.FileUtilities; import ch.systemsx.cisd.common.logging.Log4jSimpleLogger; +import ch.systemsx.cisd.common.properties.PropertyUtils; import ch.systemsx.cisd.common.utilities.SystemTimeProvider; import ch.systemsx.cisd.openbis.generic.server.CommonServiceProvider; @@ -38,6 +39,8 @@ import ch.systemsx.cisd.openbis.generic.server.CommonServiceProvider; */ public class UserManagementMaintenanceTask extends AbstractMaintenanceTask { + static final String DEACTIVATE_UNKOWN_USERS_PROPERTY = "deactivate-unknown-users"; + static final String AUDIT_LOG_FILE_PATH_PROPERTY = "audit-log-file-path"; static final String DEFAULT_AUDIT_LOG_FILE_PATH = "logs/user-management-audit_log.txt"; @@ -56,6 +59,8 @@ public class UserManagementMaintenanceTask extends AbstractMaintenanceTask private String filterKey; + private boolean deactivateUnknownUsers; + public UserManagementMaintenanceTask() { super(true); @@ -64,18 +69,13 @@ public class UserManagementMaintenanceTask extends AbstractMaintenanceTask @Override protected void setUpSpecific(Properties properties) { + deactivateUnknownUsers = PropertyUtils.getBoolean(properties, DEACTIVATE_UNKOWN_USERS_PROPERTY, true); auditLogFile = new File(properties.getProperty(AUDIT_LOG_FILE_PATH_PROPERTY, DEFAULT_AUDIT_LOG_FILE_PATH)); if (auditLogFile.isDirectory()) { throw new ConfigurationFailureException("Audit log file '" + auditLogFile.getAbsolutePath() + "' is a directory."); } ldapService = getLdapAuthenticationService(); - if (ldapService.isConfigured() == false) - { - throw new ConfigurationFailureException("There is no LDAP authentication service configured. " - + "At least 'ldap.server.url', 'ldap.security.principal.distinguished.name', " - + "'ldap.security.principal.password' have to be specified in 'service.properties'."); - } filterKey = properties.getProperty(LDAP_FILTER_KEY_PROPERTY, DEFAULT_LDAP_FILTER_KEY); String shareIdsMappingFilePath = properties.getProperty(SHARES_MAPPING_FILE_PATH_PROPERTY); if (shareIdsMappingFilePath != null) @@ -124,30 +124,36 @@ public class UserManagementMaintenanceTask extends AbstractMaintenanceTask return false; } } - List<String> ldapGroupKeys = group.getLdapGroupKeys(); - if (ldapGroupKeys == null || ldapGroupKeys.isEmpty()) - { - operationLog.error("No ldapGroupKeys specified for group '" + key + "'. Task aborted."); - return false; - } Map<String, Principal> principalsByUserId = new TreeMap<>(); - for (String ldapGroupKey : ldapGroupKeys) + List<String> users = group.getUsers(); + if (users != null && users.isEmpty() == false) { - if (StringUtils.isBlank(ldapGroupKey)) - { - operationLog.error("Empty ldapGroupKey for group '" + key + "'. Task aborted."); - return false; - - } - List<Principal> principals = getUsersOfGroup(ldapGroupKey); - if (group.isEnabled() && principals.isEmpty()) + for (String user : users) { - operationLog.error("No users found for ldapGroupKey '" + ldapGroupKey + "' for group '" + key + "'. Task aborted."); - return false; + principalsByUserId.put(user, new Principal(user, "", "", "")); } - for (Principal principal : principals) + } + List<String> ldapGroupKeys = group.getLdapGroupKeys(); + if (ldapGroupKeys != null && ldapGroupKeys.isEmpty() == false) + { + for (String ldapGroupKey : ldapGroupKeys) { - principalsByUserId.put(principal.getUserId(), principal); + if (StringUtils.isBlank(ldapGroupKey)) + { + operationLog.error("Empty ldapGroupKey for group '" + key + "'. Task aborted."); + return false; + + } + List<Principal> principals = getUsersOfGroup(ldapGroupKey); + if (group.isEnabled() && principals.isEmpty()) + { + operationLog.error("No users found for ldapGroupKey '" + ldapGroupKey + "' for group '" + key + "'. Task aborted."); + return false; + } + for (Principal principal : principals) + { + principalsByUserId.put(principal.getUserId(), principal); + } } } userManager.addGroup(group, principalsByUserId); @@ -170,6 +176,12 @@ public class UserManagementMaintenanceTask extends AbstractMaintenanceTask protected List<Principal> getUsersOfGroup(String ldapGroupKey) { + if (ldapService.isConfigured() == false) + { + throw new ConfigurationFailureException("There is no LDAP authentication service configured. " + + "At least 'ldap.server.url', 'ldap.security.principal.distinguished.name', " + + "'ldap.security.principal.password' have to be specified in 'service.properties'."); + } return ldapService.listPrincipalsByKeyValue(filterKey, ldapGroupKey); } @@ -200,7 +212,9 @@ public class UserManagementMaintenanceTask extends AbstractMaintenanceTask protected UserManager createUserManager(Log4jSimpleLogger logger, UserManagerReport report) { IAuthenticationService authenticationService = (IAuthenticationService) CommonServiceProvider.tryToGetBean("authentication-service"); - return new UserManager(authenticationService, CommonServiceProvider.getApplicationServerApi(), shareIdsMappingFile, - logger, report); + UserManager userManager = new UserManager(authenticationService, CommonServiceProvider.getApplicationServerApi(), + shareIdsMappingFile, logger, report); + userManager.setDeactivateUnknwonUsers(deactivateUnknownUsers); + return userManager; } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserManager.java index 1a6024d46fadc1d7f4bac44eb7da86b6119a2b56..b436da7ca96e4524ebdb86c8115f0e173ef8b20b 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserManager.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/task/UserManager.java @@ -133,6 +133,8 @@ public class UserManager private List<MappingAttributes> mappingAttributesList = new ArrayList<>(); + private boolean deactivateUnknownUsers; + public UserManager(IAuthenticationService authenticationService, IApplicationServerInternalApi service, File shareIdsMappingFileOrNull, ISimpleLogger logger, UserManagerReport report) @@ -185,6 +187,11 @@ public class UserManager + (StringUtils.isBlank(message) ? ". " : " (reason: " + message + "). ") + "Template schema: " + templateSchema); } + public void setDeactivateUnknwonUsers(boolean deactivateUnknownUsers) + { + this.deactivateUnknownUsers = deactivateUnknownUsers; + } + public void addGroup(UserGroup group, Map<String, Principal> principalsByUserId) { String groupCode = group.getKey().toUpperCase(); @@ -217,7 +224,10 @@ public class UserManager updateMappingFile(); manageGlobalSpaces(sessionToken, report); - revokeUsersUnkownByAuthenticationService(sessionToken, report); + if (deactivateUnknownUsers) + { + revokeUsersUnkownByAuthenticationService(sessionToken, report); + } CurrentState currentState = loadCurrentState(sessionToken, service); for (Entry<String, Map<String, Principal>> entry : usersByGroupCode.entrySet()) { diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/task/UserManagementMaintenanceTaskTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/task/UserManagementMaintenanceTaskTest.java index d1ae0444560103829fb86625880a11fb66135306..d7635e0c488232074cd5bb3f43f9727ef1518d5e 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/task/UserManagementMaintenanceTaskTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/task/UserManagementMaintenanceTaskTest.java @@ -127,17 +127,6 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas assertConfigFailure(task, "Share ids mapping file '" + mappingFile.getAbsolutePath() + "' is a directory."); } - @Test - public void testSetUpFailedBecauseLdapServiceIsNotConfigured() - { - // Given - UserManagementMaintenanceTaskWithMocks task = new UserManagementMaintenanceTaskWithMocks().withNotConfiguredLdap(); - FileUtilities.writeToFile(configFile, ""); - - // When + Then - assertConfigFailure(task, "There is no LDAP authentication service configured."); - } - @Test public void testExecuteFailedBecauseOfConfigFileHasBeenDeleted() { @@ -189,10 +178,11 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas } @Test - public void testExecuteMissingLdapGroupKeys() + public void testExecuteWithoutLdapGroupKeysAndUsers() { // Given - UserManagementMaintenanceTaskWithMocks task = new UserManagementMaintenanceTaskWithMocks(); + UserManagementMaintenanceTaskWithMocks task = new UserManagementMaintenanceTaskWithMocks() + .withUserManagerReport(new UserManagerReport(new MockTimeProvider(0, 1000))); FileUtilities.writeToFile(configFile, ""); task.setUp("", properties); FileUtilities.writeToFile(configFile, "{\"groups\": [{\"key\":\"ABC\"}]}"); @@ -209,7 +199,37 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common spaces: {}\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common samples: {}\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common experiments: {}\n" - + "ERROR OPERATION.UserManagementMaintenanceTaskWithMocks - No ldapGroupKeys specified for group 'ABC'. Task aborted.", + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group ABC[name:null, enabled:true, ldapGroupKeys:null, users:null, admins:null] with users []\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - 0 users for group ABC\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - finished", + logRecorder.getLogContent()); + } + + @Test + public void testExecuteWithUsersButWithoutLdapGroupKeys() + { + // Given + UserManagementMaintenanceTaskWithMocks task = new UserManagementMaintenanceTaskWithMocks() + .withUserManagerReport(new UserManagerReport(new MockTimeProvider(0, 1000))); + FileUtilities.writeToFile(configFile, ""); + task.setUp("", properties); + FileUtilities.writeToFile(configFile, "{\"groups\": [{\"key\":\"ABC\", \"users\":[\"alpha\", \"beta\"]}]}"); + + // When + task.execute(); + + // Then + assertEquals("INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Setup plugin \n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Plugin '' initialized. Configuration file: " + + configFile.getAbsolutePath() + "\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - manage 1 groups\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Global spaces: []\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common spaces: {}\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common samples: {}\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common experiments: {}\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group ABC[name:null, enabled:true, ldapGroupKeys:null, users:[alpha, beta], admins:null] with users [alpha=alpha, beta=beta]\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - 2 users for group ABC\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - finished", logRecorder.getLogContent()); } @@ -343,7 +363,7 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common experiments: {}\n" + "ERROR NOTIFY.UserManagementMaintenanceTaskWithMocks - Identifier template 'A' is invalid " + "(reason: No common space for common sample). Template schema: <common space code>/<common sample code>\n" - + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group SIS[name:sis, enabled:true, ldapGroupKeys:[s], admins:null] with users [u1=u1]\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group SIS[name:sis, enabled:true, ldapGroupKeys:[s], users:null, admins:null] with users [u1=u1]\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - 1 users for group SIS\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - finished", logRecorder.getLogContent()); @@ -375,7 +395,7 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common experiments: {ALPHA/B=B}\n" + "ERROR NOTIFY.UserManagementMaintenanceTaskWithMocks - Identifier template 'ALPHA/B' is invalid. " + "Template schema: <common space code>/<common project code>/<common experiment code>\n" - + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group SIS[name:sis, enabled:true, ldapGroupKeys:[s], admins:null] with users [u1=u1]\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group SIS[name:sis, enabled:true, ldapGroupKeys:[s], users:null, admins:null] with users [u1=u1]\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - 1 users for group SIS\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - finished", logRecorder.getLogContent()); @@ -395,7 +415,7 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas task.setUp("", properties); FileUtilities.writeToFile(configFile, "{\"globalSpaces\":[\"ES\"],\"commonSpaces\":{\"USER\": [\"ALPHA\"]}," + "\"commonSamples\":{\"ALPHA/B\":\"B\"},\"commonExperiments\":{\"ALPHA/P/E\":\"E\"}," - + "\"groups\": [{\"name\":\"sis\",\"key\":\"SIS\",\"ldapGroupKeys\": [\"s\"],\"admins\": [\"u2\"]}," + + "\"groups\": [{\"name\":\"sis\",\"key\":\"SIS\",\"ldapGroupKeys\": [\"s\"],\"users\":[\"u2\"],\"admins\": [\"u2\"]}," + "{\"name\":\"abc\",\"key\":\"ABC\",\"ldapGroupKeys\": [\"a\"],\"enabled\": false}]}"); // When @@ -410,9 +430,9 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common spaces: {USER=[ALPHA]}\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common samples: {ALPHA/B=B}\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common experiments: {ALPHA/P/E=E}\n" - + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group SIS[name:sis, enabled:true, ldapGroupKeys:[s], admins:[u2]] with users [u1=u1]\n" - + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - 1 users for group SIS\n" - + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group ABC[name:abc, enabled:false, ldapGroupKeys:[a], admins:null] with users [u1=u1]\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group SIS[name:sis, enabled:true, ldapGroupKeys:[s], users:[u2], admins:[u2]] with users [u1=u1, u2=u2]\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - 2 users for group SIS\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group ABC[name:abc, enabled:false, ldapGroupKeys:[a], users:null, admins:null] with users [u1=u1]\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - 1 users for disabled group ABC\n" + "ERROR NOTIFY.UserManagementMaintenanceTaskWithMocks - User management failed for the following reason(s):\n\n" + "This is a test error message\n\n" @@ -424,7 +444,7 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas + "1970-01-01 01:00:02 [CONFIG-UPDATE-START] Last modified: " + lastModified + "\n" + "{\"globalSpaces\":[\"ES\"],\"commonSpaces\":{\"USER\": [\"ALPHA\"]},\"commonSamples\":{\"ALPHA/B\":\"B\"}," + "\"commonExperiments\":{\"ALPHA/P/E\":\"E\"},\"groups\": [" - + "{\"name\":\"sis\",\"key\":\"SIS\",\"ldapGroupKeys\": [\"s\"],\"admins\": [\"u2\"]}," + + "{\"name\":\"sis\",\"key\":\"SIS\",\"ldapGroupKeys\": [\"s\"],\"users\":[\"u2\"],\"admins\": [\"u2\"]}," + "{\"name\":\"abc\",\"key\":\"ABC\",\"ldapGroupKeys\": [\"a\"],\"enabled\": false}]}\n" + "1970-01-01 01:00:03 [CONFIG-UPDATE-END] \n" + "1970-01-01 01:00:04 [ADD-AUTHORIZATION-GROUP] dummy group\n\n", @@ -464,7 +484,7 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common spaces: {}\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common samples: {}\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common experiments: {}\n" - + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group ABC[name:abc, enabled:false, ldapGroupKeys:[a], admins:null] with users [u1=u1]\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group ABC[name:abc, enabled:false, ldapGroupKeys:[a], users:null, admins:null] with users [u1=u1]\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - 1 users for disabled group ABC\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - finished\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - manage 1 groups\n" @@ -472,7 +492,7 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common spaces: {}\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common samples: {}\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common experiments: {}\n" - + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group ABC[name:abc, enabled:false, ldapGroupKeys:[a], admins:null] with users [u1=u1]\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group ABC[name:abc, enabled:false, ldapGroupKeys:[a], users:null, admins:null] with users [u1=u1]\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - 1 users for disabled group ABC\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - finished\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - manage 1 groups\n" @@ -480,7 +500,7 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common spaces: {}\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common samples: {}\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Common experiments: {}\n" - + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group ABC[name:abc, enabled:true, ldapGroupKeys:[a], admins:null] with users [u1=u1]\n" + + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - Add group ABC[name:abc, enabled:true, ldapGroupKeys:[a], users:null, admins:null] with users [u1=u1]\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - 1 users for group ABC\n" + "INFO OPERATION.UserManagementMaintenanceTaskWithMocks - finished", logRecorder.getLogContent()); @@ -598,7 +618,8 @@ public class UserManagementMaintenanceTaskTest extends AbstractFileSystemTestCas public void addGroup(UserGroup group, Map<String, Principal> principalsByUserId) { String renderedGroup = group.getKey() + "[name:" + group.getName() + ", enabled:" + group.isEnabled() - + ", ldapGroupKeys:" + group.getLdapGroupKeys() + ", admins:" + group.getAdmins() + "]"; + + ", ldapGroupKeys:" + group.getLdapGroupKeys() + ", users:" + group.getUsers() + + ", admins:" + group.getAdmins() + "]"; CommaSeparatedListBuilder builder = new CommaSeparatedListBuilder(); for (Entry<String, Principal> entry : principalsByUserId.entrySet()) {