In the past I used the Univention Corporate Server for Identity Management in some organizations. However, I find that UCS is relatively huge and I nowadays I prefer to operate a Samba server in combination with Keycloak, because it is easier to integrate into server orchestration tools. Also, Keycloak provides sufficient functionality to manage users within the Samba Active Directory. It took me quite some time to figure out how to migrate the data cleanly. The goal is to migrate the data into clean Active Directory structures. I only want to migrate the username, sn, givenName, displayName and mail attributes while keeping the objectUUID. Also, group memberships should be migrated.
One major caveat was to import the entryUUID of UCS into the objectUUID attribute of Samba. samba-tool has no parameter to set the objectGUID for a new user. A possible workaround is to use ldbmodify to import the user objects first. ldbmodify is available in the ldb-tools package on Debian based distributions.
The import assumes that the Samba server has already been provisioned with
samba-tool domain provision
The following script can be used to export the data in 2 files:
#!/bin/bash
UIDS=$(slapcat -a "(mail=*)" | grep uid: | sed "s/uid: //")
while IFS= read -r USERUID; do
echo "Exporting '$USERUID'"
USER_DATA=$(slapcat -a "(uid=$USERUID)")
USER_DN=$(echo "$USER_DATA" | grep "dn: " | sed "s/dn: //")
USER_GUID=$(echo "$USER_DATA" | grep "entryUUID: " | sed "s/entryUUID: //")
USER_MAIL=$(echo "$USER_DATA" | grep -E "^mail:" | sed "s/^mail://")
USER_FIRST_NAME=$(echo "$USER_DATA" | grep "givenName:" | sed "s/^givenName://")
USER_LAST_NAME=$(echo "$USER_DATA" | grep "sn:" | sed "s/^sn://")
USER_DISPLAY_NAME=$(echo "$USER_DATA" | grep "displayName:" | sed "s/^displayName://")
USER_NTHASH=$(echo "$USER_DATA" | grep "sambaNTPassword: " | sed "s/sambaNTPassword: //")
echo "Writing $USER_DN"
echo "dn: CN=$USERUID,CN=Users,DC=example,DC=com" >> /root/users.ldif
echo "changetype: add" >> /root/users.ldif
echo "objectclass: user" >> /root/users.ldif
echo "objectGUID: $USER_GUID" >> /root/users.ldif
echo "sAMAccountName: $USERUID" >> /root/users.ldif
echo "mail:$USER_MAIL" >> /root/users.ldif
echo "displayName:$USER_DISPLAY_NAME" >> /root/users.ldif
echo "sn:$USER_LAST_NAME" >> /root/users.ldif
echo "givenName:$USER_FIRST_NAME" >> /root/users.ldif
echo "" >> /root/users.ldif
MEMBERSHIPS=$(echo "$USER_DATA" | grep "memberOf: " | sed "s/memberOf: //" | sed "s/cn=//" | cut -d ',' -f 1)
while IFS= read -r MEMBERSHIP; do
echo "samba-tool group addmembers '$MEMBERSHIP' $USERUID" >> /root/import.sh
done <<< "$MEMBERSHIPS"
echo "pdbedit -u $USERUID --set-nt-hash $USER_NTHASH" >> /root/import.sh
done <<< "$UIDS"
EXPORT_GROUPS=$(slapcat -a "(objectClass=posixGroup)" | grep "cn: " | sed "s/cn: //")
while IFS= read -r GROUPCN; do
if [ "$GROUPCN" = "Domain Users" ] || [ "$GROUPCN" = "Domain Admins" ] || [ "$GROUPCN" = "Domain Guests" ] || [ "$GROUPCN" = "Domain Controllers" ] || [ "$GROUPCN" = "Windows Hosts" ] || [ "$GROUPCN" = "DC Backup Hosts" ] || [ "$GROUPCN" = "DC Slave Hosts" ] || [ "$GROUPCN" = "Computers" ] || [ "$GROUPCN" = "Printer-Admins" ] || [ "$GROUPCN" = "Slave Join" ] || [ "$GROUPCN" = "Backup Join" ] ; then
continue
fi
GROUP_DATA=$(slapcat -a "(cn=$GROUPCN)")
GROUP_UUID=$(echo "$GROUP_DATA" | grep "entryUUID: " | sed "s/entryUUID: //")
echo "Writing $GROUPCN"
echo "dn: CN=$GROUPCN,CN=Users,DC=example,DC=com" >> /root/users.ldif
echo "changetype: add" >> /root/users.ldif
echo "objectClass: top" >> /root/users.ldif
echo "objectClass: group" >> /root/users.ldif
echo "cn: $GROUPCN" >> /root/users.ldif
echo "name: $GROUPCN" >> /root/users.ldif
echo "objectGUID: $GROUP_UUID" >> /root/users.ldif
echo "sAMAccountName: $GROUPCN" >> /root/users.ldif
echo "" >> /root/users.ldif
done <<< "$EXPORT_GROUPS"
Now copy the created users.ldif and import.sh files into the /root directory of your new Samba server. To import the data into Samba, first import the user objects with ldbmodify:
ldbmodify -H tdb:///var/lib/samba/private/sam.ldb /root/users.ldif --relax
Finally set the group memberships and password hashes with executing the import.sh:
bash /root/import.sh