Introduce LDIF OSGi User Admin implementation
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 24 Aug 2015 18:36:11 +0000 (18:36 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 24 Aug 2015 18:36:11 +0000 (18:36 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@8336 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/BasicTestConstants.java [new file with mode: 0644]
org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifParserTest.java
org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java [new file with mode: 0644]
org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/basic.ldif [new file with mode: 0644]
org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/test.ldif [deleted file]
org.argeo.security.core/src/org/argeo/osgi/useradmin/ArgeoUserAdminException.java [new file with mode: 0644]
org.argeo.security.core/src/org/argeo/osgi/useradmin/AttributeDictionary.java [new file with mode: 0644]
org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifGroup.java [new file with mode: 0644]
org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifParser.java
org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUser.java [new file with mode: 0644]
org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java [new file with mode: 0644]

diff --git a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/BasicTestConstants.java b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/BasicTestConstants.java
new file mode 100644 (file)
index 0000000..f608cce
--- /dev/null
@@ -0,0 +1,6 @@
+package org.argeo.osgi.useradmin;
+
+interface BasicTestConstants {
+       final static String ROOT_USER_DN = "uid=root+cn=Super Admin,ou=People,dc=demo,dc=example,dc=org";
+       final static String ADMIN_GROUP_DN = "cn=admin,ou=Roles,dc=demo,dc=example,dc=org";
+}
index ae584a18c61a9ff883e33446f1a49d4871a2689d..75a5c34b3442c4d39129b4c343349dcc2ead8ccc 100644 (file)
@@ -14,13 +14,12 @@ import junit.framework.TestCase;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.codec.digest.DigestUtils;
 
-public class LdifParserTest extends TestCase {
-       public void testSimpleLdif() throws Exception {
+public class LdifParserTest extends TestCase implements BasicTestConstants {
+       public void testBasicLdif() throws Exception {
                LdifParser ldifParser = new LdifParser();
                SortedMap<LdapName, Attributes> res = ldifParser.read(getClass()
-                               .getResourceAsStream("test.ldif"));
-               LdapName rootDn = new LdapName(
-                               "uid=root+cn=Super Admin,ou=People,dc=demo,dc=example,dc=org");
+                               .getResourceAsStream("basic.ldif"));
+               LdapName rootDn = new LdapName(ROOT_USER_DN);
                Attributes rootAttributes = res.get(rootDn);
                assertNotNull(rootAttributes);
                assertEquals("Superuser", rootAttributes.get("description").get());
@@ -32,7 +31,7 @@ public class LdifParserTest extends TestCase {
                                new String(rawPwEntry));
 
                LdapName adminDn = new LdapName(
-                               "cn=admin,ou=Roles,dc=demo,dc=example,dc=org");
+                               ADMIN_GROUP_DN);
                Attributes adminAttributes = res.get(adminDn);
                assertNotNull(adminAttributes);
                Attribute memberAttribute = adminAttributes.get("member");
diff --git a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java
new file mode 100644 (file)
index 0000000..75a58d0
--- /dev/null
@@ -0,0 +1,22 @@
+package org.argeo.osgi.useradmin;
+
+import junit.framework.TestCase;
+
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+
+public class LdifUserAdminTest extends TestCase implements BasicTestConstants {
+
+       public void testBasicUserAdmin() {
+               LdifUserAdmin userAdmin = new LdifUserAdmin(getClass()
+                               .getResourceAsStream("basic.ldif"));
+               User rootUser = (User) userAdmin.getRole(ROOT_USER_DN);
+               assertNotNull(rootUser);
+               Group adminGroup = (Group) userAdmin.getRole(ADMIN_GROUP_DN);
+               assertNotNull(adminGroup);
+               Role[] members = adminGroup.getMembers();
+               assertEquals(1, members.length);
+               assertEquals(rootUser.getName(), members[0].getName());
+       }
+}
diff --git a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/basic.ldif b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/basic.ldif
new file mode 100644 (file)
index 0000000..380311f
--- /dev/null
@@ -0,0 +1,47 @@
+dn: dc=demo,dc=example,dc=org
+objectClass: domain
+objectClass: extensibleObject
+objectClass: top
+dc: demo
+
+dn: ou=Roles,dc=demo,dc=example,dc=org
+objectClass: organizationalUnit
+objectClass: top
+ou: Roles
+
+dn: ou=People,dc=demo,dc=example,dc=org
+objectClass: organizationalUnit
+objectClass: top
+ou: People
+
+dn: uid=demo,ou=People,dc=demo,dc=example,dc=org
+objectClass: organizationalPerson
+objectClass: person
+objectClass: inetOrgPerson
+objectClass: top
+cn: demo User
+description: Demo user
+givenname: Demo
+mail: demo@localhost
+sn: User
+uid: demo
+userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9
+
+dn: uid=root+cn=Super Admin,ou=People,dc=demo,dc=example,dc=org
+objectClass: person
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: top
+cn: demo User
+description: Superuser
+givenname: Root
+mail: root@localhost
+sn: Root
+uid: root
+userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9
+
+dn: cn=admin,ou=Roles,dc=demo,dc=example,dc=org
+objectClass: groupOfNames
+objectClass: top
+cn: admin
+member: uid=root+cn=Super Admin,ou=People,dc=demo,dc=example,dc=org
\ No newline at end of file
diff --git a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/test.ldif b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/test.ldif
deleted file mode 100644 (file)
index 380311f..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-dn: dc=demo,dc=example,dc=org
-objectClass: domain
-objectClass: extensibleObject
-objectClass: top
-dc: demo
-
-dn: ou=Roles,dc=demo,dc=example,dc=org
-objectClass: organizationalUnit
-objectClass: top
-ou: Roles
-
-dn: ou=People,dc=demo,dc=example,dc=org
-objectClass: organizationalUnit
-objectClass: top
-ou: People
-
-dn: uid=demo,ou=People,dc=demo,dc=example,dc=org
-objectClass: organizationalPerson
-objectClass: person
-objectClass: inetOrgPerson
-objectClass: top
-cn: demo User
-description: Demo user
-givenname: Demo
-mail: demo@localhost
-sn: User
-uid: demo
-userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9
-
-dn: uid=root+cn=Super Admin,ou=People,dc=demo,dc=example,dc=org
-objectClass: person
-objectClass: inetOrgPerson
-objectClass: organizationalPerson
-objectClass: top
-cn: demo User
-description: Superuser
-givenname: Root
-mail: root@localhost
-sn: Root
-uid: root
-userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9
-
-dn: cn=admin,ou=Roles,dc=demo,dc=example,dc=org
-objectClass: groupOfNames
-objectClass: top
-cn: admin
-member: uid=root+cn=Super Admin,ou=People,dc=demo,dc=example,dc=org
\ No newline at end of file
diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/ArgeoUserAdminException.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/ArgeoUserAdminException.java
new file mode 100644 (file)
index 0000000..70724a7
--- /dev/null
@@ -0,0 +1,19 @@
+package org.argeo.osgi.useradmin;
+
+import org.osgi.service.useradmin.UserAdmin;
+
+/**
+ * Exceptions related to Argeo's implementation of OSGi {@link UserAdmin}
+ * service.
+ */
+public class ArgeoUserAdminException extends RuntimeException {
+       private static final long serialVersionUID = 1419352360062048603L;
+
+       public ArgeoUserAdminException(String message) {
+               super(message);
+       }
+
+       public ArgeoUserAdminException(String message, Throwable e) {
+               super(message, e);
+       }
+}
diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/AttributeDictionary.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AttributeDictionary.java
new file mode 100644 (file)
index 0000000..7691d8a
--- /dev/null
@@ -0,0 +1,73 @@
+package org.argeo.osgi.useradmin;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+
+class AttributeDictionary extends Dictionary {
+       private final Attributes attributes;
+
+       public AttributeDictionary(Attributes attributes) {
+               this.attributes = attributes;
+       }
+
+       @Override
+       public int size() {
+               return attributes.size();
+       }
+
+       @Override
+       public boolean isEmpty() {
+               return attributes.size() == 0;
+       }
+
+       @Override
+       public Enumeration<String> keys() {
+               return attributes.getIDs();
+       }
+
+       @Override
+       public Enumeration<Object> elements() {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public Object get(Object key) {
+               try {
+                       return attributes.get(key.toString()).get();
+               } catch (NamingException e) {
+                       throw new ArgeoUserAdminException("Cannot get value for attribute "
+                                       + key, e);
+               }
+       }
+
+       @Override
+       public Object put(Object key, Object value) {
+               if (!(value instanceof String || value instanceof byte[]))
+                       throw new IllegalArgumentException(
+                                       "Value muste be String or byte[]");
+               try {
+                       Attribute attribute = attributes.get(key.toString());
+                       attribute = new BasicAttribute(key.toString());
+                       attribute.add(value);
+                       Attribute previousAttribute = attributes.put(attribute);
+                       if (previousAttribute != null)
+                               return previousAttribute.get();
+                       else
+                               return null;
+               } catch (NamingException e) {
+                       throw new ArgeoUserAdminException("Cannot get value for attribute "
+                                       + key, e);
+               }
+       }
+
+       @Override
+       public Object remove(Object key) {
+               throw new UnsupportedOperationException();
+       }
+
+}
diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifGroup.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifGroup.java
new file mode 100644 (file)
index 0000000..c2c6667
--- /dev/null
@@ -0,0 +1,63 @@
+package org.argeo.osgi.useradmin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+
+public class LdifGroup extends LdifUser implements Group {
+
+       public LdifGroup(LdapName dn, Attributes attributes) {
+               super(dn, attributes);
+       }
+
+       @Override
+       public boolean addMember(Role role) {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public boolean addRequiredMember(Role role) {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public boolean removeMember(Role role) {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public Role[] getMembers() {
+               Attribute memberAttribute = getAttributes().get("member");
+               if (memberAttribute == null)
+                       return new Role[0];
+               try {
+                       List<Role> roles = new ArrayList<Role>();
+                       NamingEnumeration values = memberAttribute.getAll();
+                       while (values.hasMore()) {
+                               LdapName dn = new LdapName(values.next().toString());
+                               roles.add(new LdifUser(dn, null));
+                       }
+                       return roles.toArray(new Role[roles.size()]);
+               } catch (Exception e) {
+                       throw new ArgeoUserAdminException("Cannot get members", e);
+               }
+       }
+
+       @Override
+       public Role[] getRequiredMembers() {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public int getType() {
+               return GROUP;
+       }
+
+}
index 38c37312f23b65d006d0e2fe86595dc6023b917e..56bdb54e39adbc992ca14bda6df1ce59397cf6b6 100644 (file)
@@ -72,8 +72,8 @@ class LdifParser {
                                                if (currentDn != null) {
                                                        Attributes previous = res.put(currentDn,
                                                                        currentAttributes);
-                                                       if (log.isDebugEnabled())
-                                                               log.debug("Added " + currentDn);
+                                                       if (log.isTraceEnabled())
+                                                               log.trace("Added " + currentDn);
                                                        if (previous != null) {
                                                                log.warn("There was already an entry with DN "
                                                                                + currentDn
diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUser.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUser.java
new file mode 100644 (file)
index 0000000..1de18c5
--- /dev/null
@@ -0,0 +1,59 @@
+package org.argeo.osgi.useradmin;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdmin;
+
+class LdifUser implements User {
+       private final LdapName dn;
+       private final Attributes attributes;
+
+       LdifUser(LdapName dn, Attributes attributes) {
+               this.dn = dn;
+               this.attributes = attributes;
+       }
+
+       @Override
+       public String getName() {
+               return dn.toString();
+       }
+
+       @Override
+       public int getType() {
+               return USER;
+       }
+
+       @Override
+       public Dictionary<String, Object> getProperties() {
+               if (attributes == null)
+                       throw new ArgeoUserAdminException(
+                                       "Must be loaded from user admin service");
+               return new AttributeDictionary(attributes);
+       }
+
+       @Override
+       public Dictionary<String, Object> getCredentials() {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+       @Override
+       public boolean hasCredential(String key, Object value) {
+               // TODO Auto-generated method stub
+               return false;
+       }
+
+       protected LdapName getDn() {
+               return dn;
+       }
+
+       protected Attributes getAttributes() {
+               return attributes;
+       }
+
+}
diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java
new file mode 100644 (file)
index 0000000..5796b46
--- /dev/null
@@ -0,0 +1,88 @@
+package org.argeo.osgi.useradmin;
+
+import java.io.InputStream;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.naming.InvalidNameException;
+import javax.naming.NamingEnumeration;
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.useradmin.Authorization;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdmin;
+
+public class LdifUserAdmin implements UserAdmin {
+       private SortedMap<LdapName, Role> roles = new TreeMap<LdapName, Role>();
+
+       public LdifUserAdmin(InputStream in) {
+               try {
+                       LdifParser ldifParser = new LdifParser();
+                       SortedMap<LdapName, Attributes> allEntries = ldifParser.read(in);
+                       for (LdapName key : allEntries.keySet()) {
+                               Attributes attributes = allEntries.get(key);
+                               NamingEnumeration objectClasses = attributes.get("objectClass")
+                                               .getAll();
+                               objectClasses: while (objectClasses.hasMore()) {
+                                       String objectClass = objectClasses.next().toString();
+                                       if (objectClass.equals("inetOrgPerson")) {
+                                               roles.put(key, new LdifUser(key, attributes));
+                                               break objectClasses;
+                                       } else if (objectClass.equals("groupOfNames")) {
+                                               roles.put(key, new LdifGroup(key, attributes));
+                                               break objectClasses;
+                                       }
+                               }
+                       }
+               } catch (Exception e) {
+                       throw new ArgeoUserAdminException(
+                                       "Cannot initialise user admin service from LDIF", e);
+               }
+       }
+
+       @Override
+       public Role getRole(String name) {
+               LdapName key;
+               try {
+                       key = new LdapName(name);
+               } catch (InvalidNameException e) {
+                       // TODO implements default base DN
+                       throw new IllegalArgumentException("Badly formatted role name: "
+                                       + name, e);
+               }
+
+               if (!roles.containsKey(key))
+                       return null;
+               return roles.get(key);
+       }
+
+       @Override
+       public Authorization getAuthorization(User user) {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+       @Override
+       public Role createRole(String name, int type) {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public boolean removeRole(String name) {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public Role[] getRoles(String filter) throws InvalidSyntaxException {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public User getUser(String key, String value) {
+               throw new UnsupportedOperationException();
+       }
+
+}