You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
7.3 KiB
186 lines
7.3 KiB
package de.hsfulda.informatik;
|
|
|
|
import com.google.common.base.Strings;
|
|
import com.unboundid.ldap.sdk.Attribute;
|
|
import com.unboundid.ldap.sdk.Entry;
|
|
import com.unboundid.ldap.sdk.LDAPException;
|
|
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileReader;
|
|
import java.io.IOException;
|
|
import java.security.GeneralSecurityException;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Properties;
|
|
import java.util.Set;
|
|
import java.util.TreeMap;
|
|
import java.util.TreeSet;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* Ldap sync utility
|
|
*/
|
|
public class LdapSync {
|
|
private final Properties properties = new Properties();
|
|
private final static Pattern pattern = Pattern.compile("^fd([a-z][a-z])?([0-9]*?)$");
|
|
private Map<String, Integer> userDefinedMappings = Collections.emptyMap();
|
|
|
|
public LdapSync() throws IOException, LDAPException, GeneralSecurityException {
|
|
// lade Konfiguration
|
|
properties.load(new FileReader("ldap-sync.properties"));
|
|
|
|
this.userDefinedMappings = parseUserDefinedMappings(properties.getProperty("sync.src.map", ""));
|
|
|
|
System.out.print("Abfrage der Benutzer im eDirectory...");
|
|
|
|
// lade Daten des Remote-Systems
|
|
final AccountSource remote = new AccountSource(
|
|
properties.getProperty("sync.src.host"),
|
|
Integer.parseInt(properties.getProperty("sync.src.port")),
|
|
properties.getProperty("sync.src.binddn"),
|
|
properties.getProperty("sync.src.bindpw"),
|
|
properties.getProperty("sync.src.basedn"),
|
|
properties.getProperty("sync.src.filter"),
|
|
new String[]{"cn", "givenname", "sn", "uid"}
|
|
);
|
|
|
|
System.out.print("Ok\nAbfrage der Benutzer im OpenLDAP...");
|
|
|
|
// lade Daten des lokalen Systems
|
|
final AccountSource local = new AccountSource(
|
|
properties.getProperty("sync.dst.host"),
|
|
Integer.parseInt(properties.getProperty("sync.dst.port")),
|
|
properties.getProperty("sync.dst.binddn"),
|
|
properties.getProperty("sync.dst.bindpw"),
|
|
properties.getProperty("sync.dst.basedn"),
|
|
properties.getProperty("sync.dst.filter"),
|
|
new String[]{}
|
|
);
|
|
|
|
System.out.print("Ok\n");
|
|
|
|
sync(remote, local);
|
|
}
|
|
|
|
static Map<String, Integer> parseUserDefinedMappings(final String property) {
|
|
if (Strings.isNullOrEmpty(property)) {
|
|
return Collections.emptyMap();
|
|
}
|
|
|
|
final Map<String, Integer> mappingsMap = new TreeMap<>();
|
|
final String mappingArr[] = property.split("\\s*,\\s*");
|
|
|
|
for (final String mapping : mappingArr) {
|
|
final String accountUidArr[] = mapping.split(":");
|
|
if (accountUidArr.length == 2) {
|
|
final String uid = accountUidArr[0].toLowerCase();
|
|
final int uidNumber;
|
|
|
|
try {
|
|
uidNumber = Integer.valueOf(accountUidArr[1]);
|
|
} catch (NumberFormatException e) {
|
|
System.out.println("Fehler beim Parsen der uidNumber für uid '" + uid + "'");
|
|
continue;
|
|
}
|
|
|
|
System.out.println("-> Benutzerdefinierte Zuordnung '" + uid + "' -> " + uidNumber);
|
|
mappingsMap.put(uid, uidNumber);
|
|
} else {
|
|
System.out.println("Fehler beim Parsen der Zuordnung '" + mapping + "'");
|
|
}
|
|
}
|
|
|
|
return mappingsMap;
|
|
}
|
|
|
|
LdapSync(final AccountSource remote, final AccountSource local) throws IOException, LDAPException, GeneralSecurityException {
|
|
sync(remote, local);
|
|
}
|
|
|
|
private void sync(final AccountSource remote, final AccountSource local) throws LDAPException {
|
|
Set<String> usersToBeAdded = new TreeSet<>(remote.getUsers());
|
|
usersToBeAdded.removeAll(local.getUsers());
|
|
Set<String> usersToBeDeleted = new TreeSet<>(local.getUsers());
|
|
usersToBeDeleted.removeAll(remote.getUsers());
|
|
|
|
final List<Entry> entriesToBeAdded = remote.getEntries().stream()
|
|
.filter(s -> usersToBeAdded.contains(s.getAttributeValue("cn").toLowerCase()))
|
|
.map(s -> {
|
|
final String cn = s.getAttributeValue("cn").toLowerCase();
|
|
final String dn = "cn=" + cn + "," + local.baseDN;
|
|
final Entry e = new Entry(dn);
|
|
e.addAttribute(new Attribute("objectClass", "inetOrgPerson"));
|
|
e.addAttribute(new Attribute("objectClass", "shadowAccount"));
|
|
e.addAttribute(new Attribute("objectClass", "top"));
|
|
e.addAttribute(new Attribute("objectClass", "person"));
|
|
e.addAttribute(new Attribute("objectClass", "posixAccount"));
|
|
e.addAttribute(new Attribute("cn", cn));
|
|
e.addAttribute(new Attribute("sn", s.getAttributeValue("sn")));
|
|
e.addAttribute(new Attribute("givenname", s.getAttributeValue("givenName")));
|
|
e.addAttribute(new Attribute("uid", cn));
|
|
e.addAttribute(new Attribute("uidNumber", String.valueOf(computeUid(cn, this.userDefinedMappings))));
|
|
e.addAttribute(new Attribute("gidNumber", properties.getProperty("sync.dst.gid", "1000")));
|
|
if (properties.getProperty("sync.dst.shell") != null) {
|
|
e.addAttribute(new Attribute("loginShell", properties.getProperty("sync.dst.shell")));
|
|
}
|
|
e.addAttribute(new Attribute("homeDirectory", String.format(properties.getProperty("sync.dst.home"), cn)));
|
|
e.addAttribute(new Attribute("userPassword", "{SASL}" + cn));
|
|
e.addAttribute(new Attribute("seeAlso", s.getDN()));
|
|
|
|
return e;
|
|
}).collect(Collectors.toList());
|
|
|
|
System.out.print("Zu erzeugende Benutzer: " + entriesToBeAdded.size() + ", Zu löschende Benutzer: " + usersToBeDeleted.size() + "\n");
|
|
|
|
local.del(usersToBeDeleted);
|
|
local.add(entriesToBeAdded);
|
|
}
|
|
|
|
static Integer computeUid(final String cn) {
|
|
return computeUid(cn, Collections.emptyMap());
|
|
}
|
|
|
|
static Integer computeUid(final String cn, final Map<String, Integer> mappings) {
|
|
if (mappings.containsKey(cn)) {
|
|
return mappings.get(cn);
|
|
}
|
|
|
|
final Matcher m = pattern.matcher(cn);
|
|
|
|
if (m.find()) {
|
|
int a = 0;
|
|
int b = 0;
|
|
|
|
if (m.group(1) != null) {
|
|
a = m.group(1).charAt(0) - 96;
|
|
b = m.group(1).charAt(1) - 96;
|
|
}
|
|
|
|
final int s = m.group(2).length();
|
|
final int z = Integer.parseInt(m.group(2));
|
|
|
|
final int uid = (a * 1000 + b * 10 + s) * 10000 + z;
|
|
|
|
return uid;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
try {
|
|
final LdapSync ldapSync = new LdapSync();
|
|
} catch (FileNotFoundException e) {
|
|
e.printStackTrace();
|
|
} catch (LDAPException e) {
|
|
e.printStackTrace();
|
|
} catch (GeneralSecurityException e) {
|
|
e.printStackTrace();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|