From e921c662016dd893e60f3e801eb86d676adcb77d Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sun, 26 Jun 2022 20:50:57 +0200 Subject: [PATCH] Support IPA --- .../osgi/useradmin/DirectoryUserAdmin.java | 24 ++++++++++++++--- .../directory/ldap/AbstractLdapDirectory.java | 26 +++++++++++-------- .../argeo/util/directory/ldap/IpaUtils.java | 22 ++++++++++++---- .../argeo/util/directory/ldap/LdapDao.java | 9 ++++--- .../directory/ldap/LdapHierarchyUnit.java | 2 +- 5 files changed, 59 insertions(+), 24 deletions(-) diff --git a/org.argeo.util/src/org/argeo/osgi/useradmin/DirectoryUserAdmin.java b/org.argeo.util/src/org/argeo/osgi/useradmin/DirectoryUserAdmin.java index 6f12195dc..6f3bd1a68 100644 --- a/org.argeo.util/src/org/argeo/osgi/useradmin/DirectoryUserAdmin.java +++ b/org.argeo.util/src/org/argeo/osgi/useradmin/DirectoryUserAdmin.java @@ -26,6 +26,7 @@ import org.argeo.util.directory.DirectoryConf; import org.argeo.util.directory.DirectoryDigestUtils; import org.argeo.util.directory.HierarchyUnit; import org.argeo.util.directory.ldap.AbstractLdapDirectory; +import org.argeo.util.directory.ldap.LdapDao; import org.argeo.util.directory.ldap.LdapEntry; import org.argeo.util.directory.ldap.LdapEntryWorkingCopy; import org.argeo.util.directory.ldap.LdapNameUtils; @@ -65,7 +66,13 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm */ protected AbstractLdapDirectory scope(User user) { - throw new UnsupportedAddressTypeException(); + if (getDirectoryDao() instanceof LdapDao) { + return scopeLdap(user); + } else if (getDirectoryDao() instanceof LdifDao) { + return scopeLdif(user); + } else { + throw new IllegalStateException("Unsupported DAO " + getDirectoryDao().getClass()); + } } protected DirectoryUserAdmin scopeLdap(User user) { @@ -83,7 +90,9 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm } else { properties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI"); } - return new DirectoryUserAdmin(null, properties, true); + DirectoryUserAdmin scopedDirectory = new DirectoryUserAdmin(null, properties, true); + scopedDirectory.init(); + return scopedDirectory; } protected DirectoryUserAdmin scopeLdif(User user) { @@ -108,6 +117,7 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm // scopedUserAdmin.users = Collections.unmodifiableNavigableMap(users); // FIXME do it better ((LdifDao) getDirectoryDao()).scope((LdifDao) scopedUserAdmin.getDirectoryDao()); + scopedUserAdmin.init(); return scopedUserAdmin; } @@ -125,7 +135,12 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm @Override public Role getRoleByPath(String path) { - return (Role) doGetRole(pathToName(path)); + LdapEntry entry = doGetRole(pathToName(path)); + if (!(entry instanceof Role)) { + throw new IllegalStateException("Path must be a UserAdmin Role."); + } else { + return (Role) entry; + } } protected List getAllRoles(DirectoryUser user) { @@ -143,7 +158,8 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm LdapEntry entry = (LdapEntry) user; collectGroups(entry, allEntries); for (LdapEntry e : allEntries) { - allRoles.add((Role) e); + if (e instanceof Role) + allRoles.add((Role) e); } // Attributes attrs = user.getAttributes(); // // TODO centralize attribute name diff --git a/org.argeo.util/src/org/argeo/util/directory/ldap/AbstractLdapDirectory.java b/org.argeo.util/src/org/argeo/util/directory/ldap/AbstractLdapDirectory.java index 55449a707..9c35e4660 100644 --- a/org.argeo.util/src/org/argeo/util/directory/ldap/AbstractLdapDirectory.java +++ b/org.argeo.util/src/org/argeo/util/directory/ldap/AbstractLdapDirectory.java @@ -113,18 +113,22 @@ public abstract class AbstractLdapDirectory implements Directory, XAResourceProv disabled = Boolean.parseBoolean(disabledStr); else disabled = false; - - URI u = URI.create(uri); - if (!getRealm().isEmpty() || DirectoryConf.SCHEME_LDAP.equals(u.getScheme()) - || DirectoryConf.SCHEME_LDAPS.equals(u.getScheme())) { + if (!getRealm().isEmpty()) { + // IPA multiple LDAP causes URI parsing to fail + // TODO manage generic redundant LDAP case directoryDao = new LdapDao(this); - } else if (DirectoryConf.SCHEME_FILE.equals(u.getScheme())) { - directoryDao = new LdifDao(this); - } else if (DirectoryConf.SCHEME_OS.equals(u.getScheme())) { - directoryDao = new OsUserDirectory(this); - // singleUser = true; } else { - throw new IllegalArgumentException("Unsupported scheme " + u.getScheme()); + URI u = URI.create(uri); + if (DirectoryConf.SCHEME_LDAP.equals(u.getScheme()) || DirectoryConf.SCHEME_LDAPS.equals(u.getScheme())) { + directoryDao = new LdapDao(this); + } else if (DirectoryConf.SCHEME_FILE.equals(u.getScheme())) { + directoryDao = new LdifDao(this); + } else if (DirectoryConf.SCHEME_OS.equals(u.getScheme())) { + directoryDao = new OsUserDirectory(this); + // singleUser = true; + } else { + throw new IllegalArgumentException("Unsupported scheme " + u.getScheme()); + } } xaResource = new WorkingCopyXaResource<>(directoryDao); } @@ -338,7 +342,7 @@ public abstract class AbstractLdapDirectory implements Directory, XAResourceProv for (int i = 0; i < segments.length; i++) { String segment = segments[i]; // TODO make attr names configurable ? - String attr = LdapAttrs.ou.name(); + String attr = path.startsWith("accounts/")/* IPA */ ? LdapAttrs.cn.name() : LdapAttrs.ou.name(); if (parentRdn != null) { if (getUserBaseRdn().equals(parentRdn)) attr = LdapAttrs.uid.name(); diff --git a/org.argeo.util/src/org/argeo/util/directory/ldap/IpaUtils.java b/org.argeo.util/src/org/argeo/util/directory/ldap/IpaUtils.java index 861eb4f1f..53c30848b 100644 --- a/org.argeo.util/src/org/argeo/util/directory/ldap/IpaUtils.java +++ b/org.argeo.util/src/org/argeo/util/directory/ldap/IpaUtils.java @@ -12,6 +12,7 @@ import java.util.List; import javax.naming.InvalidNameException; import javax.naming.NamingException; import javax.naming.ldap.LdapName; +import javax.naming.ldap.Rdn; import org.argeo.util.directory.DirectoryConf; import org.argeo.util.naming.LdapAttrs; @@ -19,15 +20,26 @@ import org.argeo.util.naming.dns.DnsBrowser; /** Free IPA specific conventions. */ public class IpaUtils { - public final static String IPA_USER_BASE = "cn=users,cn=accounts"; - public final static String IPA_GROUP_BASE = "cn=groups,cn=accounts"; - public final static String IPA_ROLE_BASE = "cn=roles,cn=accounts"; + public final static String IPA_USER_BASE = "cn=users"; + public final static String IPA_GROUP_BASE = "cn=groups"; + public final static String IPA_ROLE_BASE = "cn=roles"; public final static String IPA_SERVICE_BASE = "cn=services,cn=accounts"; + public final static Rdn IPA_ACCOUNTS_RDN; + static { + try { + IPA_ACCOUNTS_RDN = new Rdn(LdapAttrs.cn.name(), "accounts"); + } catch (InvalidNameException e) { + // should not happen + throw new IllegalStateException(e); + } + } + private final static String KRB_PRINCIPAL_NAME = LdapAttrs.krbPrincipalName.name().toLowerCase(); public final static String IPA_USER_DIRECTORY_CONFIG = DirectoryConf.userBase + "=" + IPA_USER_BASE + "&" - + DirectoryConf.groupBase + "=" + IPA_GROUP_BASE + "&" + DirectoryConf.readOnly + "=true"; + + DirectoryConf.groupBase + "=" + IPA_GROUP_BASE + "&" + DirectoryConf.systemRoleBase + "=" + IPA_ROLE_BASE + + "&" + DirectoryConf.readOnly + "=true"; @Deprecated static String domainToUserDirectoryConfigPath(String realm) { @@ -61,7 +73,7 @@ public class IpaUtils { String baseDn = domainToBaseDn(kname[1]); String dn; if (!username.contains("/")) - dn = LdapAttrs.uid + "=" + username + "," + IPA_USER_BASE + "," + baseDn; + dn = LdapAttrs.uid + "=" + username + "," + IPA_USER_BASE + "," + IPA_ACCOUNTS_RDN + "," + baseDn; else dn = KRB_PRINCIPAL_NAME + "=" + kerberosName + "," + IPA_SERVICE_BASE + "," + baseDn; try { diff --git a/org.argeo.util/src/org/argeo/util/directory/ldap/LdapDao.java b/org.argeo.util/src/org/argeo/util/directory/ldap/LdapDao.java index d93fb7fdf..c33b50f65 100644 --- a/org.argeo.util/src/org/argeo/util/directory/ldap/LdapDao.java +++ b/org.argeo.util/src/org/argeo/util/directory/ldap/LdapDao.java @@ -83,8 +83,9 @@ public class LdapDao extends AbstractLdapDirectoryDao { // int roleType = roleType(name); LdapEntry res; Rdn technicalRdn = LdapNameUtils.getParentRdn(name); - if (getDirectory().getGroupBaseRdn().equals(technicalRdn) - || getDirectory().getSystemRoleBaseRdn().equals(technicalRdn)) + if (getDirectory().getGroupBaseRdn().equals(technicalRdn)) + res = newGroup(name, attrs); + else if (getDirectory().getSystemRoleBaseRdn().equals(technicalRdn)) res = newGroup(name, attrs); else if (getDirectory().getUserBaseRdn().equals(technicalRdn)) res = newUser(name, attrs); @@ -218,6 +219,8 @@ public class LdapDao extends AbstractLdapDirectoryDao { try { String searchFilter = "(|(" + objectClass + "=" + LdapObjs.organizationalUnit.name() + ")(" + objectClass + "=" + LdapObjs.organization.name() + "))"; +// String searchFilter = "(|(" + objectClass + "=" + LdapObjs.organizationalUnit.name() + ")(" + objectClass +// + "=" + LdapObjs.organization.name() + ")(cn=accounts)(cn=users)(cn=groups))"; SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE); @@ -248,7 +251,7 @@ public class LdapDao extends AbstractLdapDirectoryDao { if (getDirectory().getBaseDn().equals(dn)) return getDirectory(); if (!dn.startsWith(getDirectory().getBaseDn())) - throw new IllegalArgumentException(dn + " does not start with abse DN " + getDirectory().getBaseDn()); + throw new IllegalArgumentException(dn + " does not start with base DN " + getDirectory().getBaseDn()); Attributes attrs = ldapConnection.getAttributes(dn); return new LdapHierarchyUnit(getDirectory(), dn, attrs); } catch (NamingException e) { diff --git a/org.argeo.util/src/org/argeo/util/directory/ldap/LdapHierarchyUnit.java b/org.argeo.util/src/org/argeo/util/directory/ldap/LdapHierarchyUnit.java index c2fdef4d2..8579bc5fd 100644 --- a/org.argeo.util/src/org/argeo/util/directory/ldap/LdapHierarchyUnit.java +++ b/org.argeo.util/src/org/argeo/util/directory/ldap/LdapHierarchyUnit.java @@ -15,7 +15,7 @@ public class LdapHierarchyUnit extends DefaultLdapEntry implements HierarchyUnit Rdn rdn = LdapNameUtils.getLastRdn(dn); functional = !(directory.getUserBaseRdn().equals(rdn) || directory.getGroupBaseRdn().equals(rdn) - || directory.getSystemRoleBaseRdn().equals(rdn)); + || directory.getSystemRoleBaseRdn().equals(rdn) ); } @Override -- 2.39.2