Support IPA
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 26 Jun 2022 18:50:57 +0000 (20:50 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 26 Jun 2022 18:50:57 +0000 (20:50 +0200)
org.argeo.util/src/org/argeo/osgi/useradmin/DirectoryUserAdmin.java
org.argeo.util/src/org/argeo/util/directory/ldap/AbstractLdapDirectory.java
org.argeo.util/src/org/argeo/util/directory/ldap/IpaUtils.java
org.argeo.util/src/org/argeo/util/directory/ldap/LdapDao.java
org.argeo.util/src/org/argeo/util/directory/ldap/LdapHierarchyUnit.java

index 6f12195dc3c1d6ea6c52b1b056b0fecafe512b0a..6f3bd1a6865695cbdbc48729c10a7fda745fc156 100644 (file)
@@ -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<Role> 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
index 55449a70748f3a0f7b4bf079123adc70988b4b7b..9c35e4660797a252a98505d701f711f4a709e4e6 100644 (file)
@@ -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();
index 861eb4f1fc099564637f3ab2f0afcacacd7e74b0..53c30848b9fb40885285ad4417234189ca6c0e41 100644 (file)
@@ -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 {
index d93fb7fdf62074d5be80f53563a41992bb50aa69..c33b50f65fb9a1a781bb62de4535b63b25198c63 100644 (file)
@@ -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) {
index c2fdef4d229d5eb76faf342ccd571d1f6e23f72e..8579bc5fdc5697367999da21f919790943e9af7b 100644 (file)
@@ -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