Hello,
I would like to present in this post, the LDAP servers configuration in Documentum Administrator (DA) and the dm_LDAPSynchronization job.
Creation of LDAP server configuration:
- Go to the LDAP Servers node in DA:
- Click on the FILE > LDAP Server Configuration menu:
- Fill in the informations concerning the LDAP server:
Warning: the name of LDAP Server Configuration must be identical to domain name.
In update mode, the password is necessary in order to modify others informations: - Go on to the Sync & Authentication tab:
- Go on to the Mapping tab:
- Go on to the Failover tab:
LDAP Synchronisation job : dm_LDAPSynchronization:
- Go to the Jobs node in DA:
- Go on to the Job Properties:
- Go on to the Schedule tab:
- Go on to the Method tab:
- Go on to the SysObject Info tab:
The job dm_LDAPSynchronization creates item of « dm_job_request » type for the jobs :
+ dm_UserRename : « object_name=’UserRename’, job_name=’dm_UserRename’ » to rename users
+ dm_GroupRename : « object_name=’GroupRename’, job_name=’dm_GroupRename’ » to rename groups
DQL: List LDAP being used to authenticate users
- Source of Users
select distinct user_source from dm_user; -------------- user_source -------------- LDAP inline password ''
- OS Users
select user_login_name, user_login_domain from dm_user where user_source = ' '; ------------------------------------------ user_login_name | user_login_domain ------------------------------------------ DOCUMENTUM | dmadmin | MYDCTMSERVER dm_superusers | dm_superusers_dynamic | dm_browse_all | dm_browse_all_dynamic | dm_retention_managers | dm_retention_users | ...
- LDAP Users
select user_login_name, user_login_domain from dm_user where user_source = 'LDAP'; ------------------------------------------ user_login_name | user_login_domain ------------------------------------------ myuser1 | my-ad myuser2 | my-ad myuser3 | my-ad myuser4 | my-ad myuser5 | my-ad myuser6 | my-ad ...
- Inline Password Users
select user_login_name, user_login_domain from dm_user where user_source = 'inline password'; ------------------------------------------ user_login_name | user_login_domain ------------------------------------------ mytestuser1 | mytestuser2 | dmadmin_TEST | testread | ...
Class for correction the user based on the log of dm_LDAPSynchronization job:
package com.java.lu.business.service.ecm.utils.repair; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.text.MessageFormat; import java.util.Calendar; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import com.documentum.com.DfClientX; import com.documentum.com.IDfClientX; import com.documentum.fc.client.DfAuthenticationException; import com.documentum.fc.client.DfIdentityException; import com.documentum.fc.client.DfPrincipalException; import com.documentum.fc.client.DfQuery; import com.documentum.fc.client.DfServiceException; import com.documentum.fc.client.IDfClient; import com.documentum.fc.client.IDfDocbaseMap; import com.documentum.fc.client.IDfDocument; import com.documentum.fc.client.IDfQuery; import com.documentum.fc.client.IDfSession; import com.documentum.fc.client.IDfSessionManager; import com.documentum.fc.client.IDfUser; import com.documentum.fc.common.DfException; import com.documentum.fc.common.DfLoginInfo; public class CorrectLDAP { private static class User { final private String cn; private String username; private String uniqueId; private boolean readUserName; private boolean readUniqueId; public User(String cn) { this.cn = cn; } public void setUsername(String username) { this.username = username; } public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @Override public String toString() { return MessageFormat.format("userName:{0} - uniqueId:{1} - cn:{2}", username, uniqueId, cn); } } private final static Pattern CN_NAME_PATTERN = Pattern.compile("User DN: (.*)$"); private final static Pattern UNIQUE_ID_PATTERN = Pattern.compile("--Unique Id--:$"); private final static Pattern UNIQUE_ID_SPLITER = Pattern.compile("([^:]*):([a-f0-9]{32})"); private final static Pattern USER_NAME_PATTERN = Pattern.compile("sAMAccountName:$"); private final static Pattern VALUE_PATTERN = Pattern.compile("\\t\\t(.*)$"); private final static Pattern END_PATTERN = Pattern.compile(" [-*]{81}$"); private User currentUser; Map<String, User> map = new TreeMap<>(); public void processLine(String line) { Matcher matcher; if ((matcher = CN_NAME_PATTERN.matcher(line)).find()) { String cn = matcher.group(1); if (!map.containsKey(cn)) { currentUser = new User(cn); } } else if (currentUser != null) { if ((matcher = END_PATTERN.matcher(line)).find()) { if (!map.containsKey(currentUser.cn)) { map.put(currentUser.cn, currentUser); currentUser = null; } } else { if ((matcher = USER_NAME_PATTERN.matcher(line)).find()) { currentUser.readUserName = true; } else if ((matcher = UNIQUE_ID_PATTERN.matcher(line)).find()) { currentUser.readUniqueId = true; } else if (currentUser.readUserName) { currentUser.readUserName = false; if ((matcher = VALUE_PATTERN.matcher(line)).find()) { currentUser.setUsername(matcher.group(1)); } else { printWriter.println(MessageFormat.format("#Unable to retrieve UserName for {0} : ''{1}''", currentUser.cn, line)); } } else if (currentUser.readUniqueId) { currentUser.readUniqueId = false; if ((matcher = VALUE_PATTERN.matcher(line)).find()) { currentUser.setUniqueId(matcher.group(1)); } else { printWriter.println(MessageFormat.format("#Unable to retrieve UniqueId for {0} : ''{1}''", currentUser.cn, line)); } } } } } public void printTable() { int i = 0; for (Entry<String, User> entry : map.entrySet()) { printWriter.println(MessageFormat.format("{0,number,00000} - {1}", ++i, entry.getValue())); } } private final IDfClientX clientx; private final IDfClient client; private IDfSessionManager sMgr; private PrintWriter printWriter; private CorrectLDAP() throws DfException { this.clientx = new DfClientX(); this.client = clientx.getLocalClient(); } public CorrectLDAP(String username, String password) throws DfException { this(); IDfSessionManager sMgr = client.newSessionManager(); sMgr.setIdentity(IDfSessionManager.ALL_DOCBASES, new DfLoginInfo(username, password)); this.sMgr = sMgr; this.printWriter = new PrintWriter(System.out); } public CorrectLDAP(IDfSessionManager sMgr, PrintWriter printWriter) throws DfException { this(); this.sMgr = sMgr; this.printWriter = printWriter; } public static void main(String[] args) throws IOException, DfException { CorrectLDAP correctLDAP = new CorrectLDAP(args[0], args[1]); correctLDAP.setUpdateLdapDN(true); correctLDAP.setUpdateGlobalUniqueId(true); correctLDAP.setUpdateDomain(false); correctLDAP.setLaunchUpdate(false); correctLDAP.correctLdap(); } public void setUpdateDomain(boolean updateDomain) { this.updateDomain = updateDomain; } public void setUpdateGlobalUniqueId(boolean updateGlobalUniqueId) { this.updateGlobalUniqueId = updateGlobalUniqueId; } public void setUpdateLdapDN(boolean updateLdapDN) { this.updateLdapDN = updateLdapDN; } public void setLaunchUpdate(boolean launchUpdate) { this.launchUpdate = launchUpdate; } private boolean updateLdapDN = true; private boolean updateGlobalUniqueId = true; private boolean updateDomain = true; private boolean launchUpdate = false; public void correctLdap() throws DfException, IOException { IDfDocbaseMap dfDocbaseMap = client.getDocbaseMap(); for (int i = 0; i < dfDocbaseMap.getDocbaseCount(); i++) { String repository = dfDocbaseMap.getDocbaseName(i); correctLdap(repository); } } public void correctLdap(String repository) throws DfIdentityException, DfAuthenticationException, DfPrincipalException, DfServiceException, DfException, IOException { IDfSession dfSession = sMgr.newSession(repository); try { boolean transaction = false; boolean noError = false; try { if (launchUpdate && !dfSession.isTransactionActive()) { dfSession.beginTrans(); transaction = true; } currentUser = null; map.clear(); IDfDocument dfDocument = (IDfDocument) dfSession.getObjectByQualification("dm_document WHERE FOLDER('/Temp/Jobs/dm_LDAPSynchronization') ORDER BY r_creation_date DESC ENABLE(RETURN_TOP 1)"); if (dfDocument != null) { printWriter.println("# *******************************"); printWriter.println("# * " + repository); printWriter.println("# *******************************"); try (InputStream inputStream = dfDocument.getContent(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { for (String line; (line = bufferedReader.readLine()) != null;) { processLine(line); } } boolean foundError = false; for (User user : map.values()) { IDfUser dfUser = dfSession.getUser(user.username); if (dfUser != null) { String dql = null; if (updateLdapDN && StringUtils.isNotBlank(user.cn) && !user.cn.contains("?") && !dfUser.getString("user_ldap_dn").equals(user.cn)) { dql = MessageFormat.format("UPDATE dm_user OBJECTS SET user_ldap_dn = ''{0}'' WHERE user_name = ''{1}'';", StringUtils.replace(user.cn, "'", "''"), StringUtils.replace(user.username, "'", "''")); } if (updateGlobalUniqueId && StringUtils.isNotBlank(user.uniqueId) && !dfUser.getString("user_global_unique_id").equals(user.uniqueId)) { Matcher matcher = UNIQUE_ID_SPLITER.matcher(user.uniqueId); if (matcher.matches()) { if (updateDomain) { if (!dfUser.getString("user_global_unique_id").equals(user.uniqueId) || !dfUser.getString("user_login_domain").equals(matcher.group(2))) { dql = MessageFormat.format("UPDATE dm_user OBJECTS SET user_global_unique_id = ''{0}'', SET user_login_domain = ''{1}'' WHERE user_name = ''{2}'';", StringUtils.replace(user.uniqueId, "'", "''"), StringUtils.replace(matcher.group(1), "'", "''"), StringUtils.replace(user.username, "'", "''")); } } else { if (!dfUser.getString("user_global_unique_id").endsWith(matcher.group(2))) { dql = MessageFormat.format("UPDATE dm_user OBJECTS SET user_global_unique_id = ''{0}:{1}'' WHERE user_name = ''{2}'';", StringUtils.replace(dfUser.getString("user_login_domain"), "'", "''"), StringUtils.replace(matcher.group(2), "'", "''"), StringUtils.replace(user.username, "'", "''")); } } } } if (dql != null) { foundError = true; printWriter.print(dql); if (launchUpdate) { new DfQuery(dql).execute(dfSession, IDfQuery.DF_EXEC_QUERY).close(); printWriter.print(" => OK"); } printWriter.println(); } } } // relancer le LDAP à une date inférieure if (foundError) { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.MILLISECOND, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.DAY_OF_MONTH, 1); calendar.add(Calendar.MONTH, -1); String dql = MessageFormat.format("UPDATE dm_ldap_config OBJECTS SET a_last_run = ''{0,date,yyyyMMddHHmmss.S}Z'' WHERE a_last_run != '' '';", calendar.getTime()); printWriter.print(dql); if (launchUpdate) { new DfQuery(dql).execute(dfSession, IDfQuery.DF_EXEC_QUERY).close(); printWriter.print(" => OK"); } printWriter.println(); } printWriter.println("#======================================================="); noError = true; } } finally { if (transaction) { if (noError) { dfSession.commitTrans(); } else { dfSession.abortTrans(); } } } } finally { sMgr.release(dfSession); } } }
Best regards,
Huseyin OZVEREN