From 48a1e034607afb28d84480463b57f74a80a29929 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Wed, 16 Sep 2015 08:38:39 +0000 Subject: [PATCH] Improve properties git-svn-id: https://svn.argeo.org/commons/trunk@8408 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- demo/argeo_node_rap.properties | 10 +-- .../cms/internal/kernel/KernelConstants.java | 2 +- .../cms/internal/kernel/NodeSecurity.java | 8 +-- .../cms/internal/kernel/NodeUserAdmin.java | 55 ++++++++------- .../osgi/useradmin/AbstractUserDirectory.java | 14 ++-- .../argeo/osgi/useradmin/LdifUserAdmin.java | 4 +- ...dapProperties.java => UserAdminProps.java} | 67 +++++++++++++++---- .../argeo/osgi/useradmin/UserDirectory.java | 23 +++++++ 8 files changed, 126 insertions(+), 57 deletions(-) rename org.argeo.security.core/src/org/argeo/osgi/useradmin/{LdapProperties.java => UserAdminProps.java} (67%) create mode 100644 org.argeo.security.core/src/org/argeo/osgi/useradmin/UserDirectory.java diff --git a/demo/argeo_node_rap.properties b/demo/argeo_node_rap.properties index 2c9d5d842..52eea6a30 100644 --- a/demo/argeo_node_rap.properties +++ b/demo/argeo_node_rap.properties @@ -12,7 +12,12 @@ org.eclipse.gemini.blueprint.extender argeo.osgi.start.4.workbench=\ org.eclipse.equinox.http.registry,\ -#argeo.node.useradmin.uri="\ +org.osgi.framework.security=osgi +java.security.policy=file:../../all.policy + +argeo.node.useradmin.uris=ldap://uid=admin,ou=system:secret@localhost:10389\ +/dc=example,dc=com?userBase=ou=users&groupBase=ou=groups +#argeo.node.useradmin.uris="\ #ldap://uid=admin,ou=system:secret\ #@localhost:10389\ #/dc=example,dc=com\ @@ -20,9 +25,6 @@ org.eclipse.equinox.http.registry,\ #&userObjectClass=inetOrgPerson \ #dc=example,dc=org.ldif" -org.osgi.framework.security=osgi -java.security.policy=file:../../all.policy - # HTTP org.osgi.service.http.port=7070 org.eclipse.equinox.http.jetty.log.stderr.threshold=info diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java index e0d237da1..663c2b937 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java @@ -19,7 +19,7 @@ public interface KernelConstants { // Node Security final static String ROLES_URI = "argeo.node.roles.uri"; /** URI to an LDIF file or LDAP server used as initialization or backend */ - final static String USERADMIN_URI = "argeo.node.useradmin.uri"; + final static String USERADMIN_URIS = "argeo.node.useradmin.uris"; final static String[] DEFAULT_CNDS = { "/org/argeo/jcr/argeo.cnd", "/org/argeo/cms/cms.cnd" }; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java index aed824fbd..0b6ce9a85 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java @@ -101,13 +101,11 @@ class NodeSecurity implements AuthenticationManager { } public void publish() { + userAdminReg = bundleContext.registerService(UserAdmin.class, + userAdmin, userAdmin.currentState()); + // dummy auth manager, in order to smooth transition from Argeo 1 authenticationManagerReg = bundleContext.registerService( AuthenticationManager.class, this, null); - Hashtable properties = new Hashtable(); - // properties.put(KernelConstants.USERADMIN_URI, - // userAdmin.asConfigUris()); - userAdminReg = bundleContext.registerService(UserAdmin.class, - userAdmin, properties); } void destroy() { diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java index 9227eaeb9..7ead08151 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java @@ -9,6 +9,7 @@ import java.util.Arrays; import java.util.Dictionary; import java.util.HashMap; import java.util.HashSet; +import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Set; @@ -22,8 +23,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; import org.argeo.cms.KernelHeader; -import org.argeo.osgi.useradmin.AbstractUserDirectory; -import org.argeo.osgi.useradmin.LdapProperties; +import org.argeo.osgi.useradmin.UserDirectory; +import org.argeo.osgi.useradmin.UserAdminProps; import org.argeo.osgi.useradmin.LdapUserAdmin; import org.argeo.osgi.useradmin.LdifUserAdmin; import org.argeo.osgi.useradmin.UserDirectoryException; @@ -54,7 +55,7 @@ public class NodeUserAdmin implements UserAdmin { nodeBaseDir.mkdirs(); String userAdminUri = KernelUtils - .getFrameworkProp(KernelConstants.USERADMIN_URI); + .getFrameworkProp(KernelConstants.USERADMIN_URIS); if (userAdminUri == null) { String demoBaseDn = "dc=example,dc=com"; File businessRolesFile = new File(nodeBaseDir, demoBaseDn + ".ldif"); @@ -88,16 +89,16 @@ public class NodeUserAdmin implements UserAdmin { throw new CmsException( "Cannot interpret " + uri + " as an uri", e); } - Dictionary properties = LdapProperties.uriAsProperties(u + Dictionary properties = UserAdminProps.uriAsProperties(u .toString()); - AbstractUserDirectory businessRoles; + UserDirectory businessRoles; if (u.getScheme().startsWith("ldap")) { businessRoles = new LdapUserAdmin(properties); } else { businessRoles = new LdifUserAdmin(properties); } businessRoles.init(); - addUserAdmin(businessRoles.getBaseDn(), businessRoles); + addUserAdmin(businessRoles.getBaseDn(), (UserAdmin) businessRoles); if (log.isDebugEnabled()) log.debug("User directory " + businessRoles.getBaseDn() + " [" + u.getScheme() + "] enabled."); @@ -119,14 +120,14 @@ public class NodeUserAdmin implements UserAdmin { nodeRolesUri = nodeRolesFile.toURI().toString(); } - Dictionary nodeRolesProperties = LdapProperties + Dictionary nodeRolesProperties = UserAdminProps .uriAsProperties(nodeRolesUri); - if (!nodeRolesProperties.get(LdapProperties.baseDn.getFullName()) + if (!nodeRolesProperties.get(UserAdminProps.baseDn.getFullName()) .equals(baseNodeRoleDn)) { throw new CmsException("Invalid base dn for node roles"); // TODO deal with "mounted" roles with a different baseDN } - AbstractUserDirectory nodeRoles; + UserDirectory nodeRoles; if (nodeRolesUri.startsWith("ldap")) { nodeRoles = new LdapUserAdmin(nodeRolesProperties); } else { @@ -134,31 +135,33 @@ public class NodeUserAdmin implements UserAdmin { } nodeRoles.setExternalRoles(this); nodeRoles.init(); - addUserAdmin(baseNodeRoleDn, nodeRoles); + addUserAdmin(baseNodeRoleDn, (UserAdmin)nodeRoles); if (log.isTraceEnabled()) log.trace("Node roles enabled."); } - String asConfigUris() { - StringBuilder buf = new StringBuilder(); + Dictionary currentState() { + Dictionary res = new Hashtable(); for (LdapName name : userAdmins.keySet()) { - buf.append('/').append(name.toString()); - if (userAdmins.get(name) instanceof AbstractUserDirectory) { - AbstractUserDirectory userDirectory = (AbstractUserDirectory) userAdmins + StringBuilder buf = new StringBuilder(); + if (userAdmins.get(name) instanceof UserDirectory) { + UserDirectory userDirectory = (UserDirectory) userAdmins .get(name); - if (userDirectory.isReadOnly()) - buf.append('?').append(LdapProperties.readOnly.name()) - .append("=true"); + String uri = UserAdminProps.propertiesAsUri( + userDirectory.getProperties()).toString(); + res.put(uri, ""); + } else { + buf.append('/').append(name.toString()) + .append("?readOnly=true"); } - buf.append(' '); } - return buf.toString(); + return res; } public void destroy() { for (LdapName name : userAdmins.keySet()) { - if (userAdmins.get(name) instanceof AbstractUserDirectory) { - AbstractUserDirectory userDirectory = (AbstractUserDirectory) userAdmins + if (userAdmins.get(name) instanceof UserDirectory) { + UserDirectory userDirectory = (UserDirectory) userAdmins .get(name); userDirectory.destroy(); } @@ -283,12 +286,12 @@ public class NodeUserAdmin implements UserAdmin { } public void setTransactionManager(TransactionManager transactionManager) { - if (nodeRoles instanceof AbstractUserDirectory) - ((AbstractUserDirectory) nodeRoles) + if (nodeRoles instanceof UserDirectory) + ((UserDirectory) nodeRoles) .setTransactionManager(transactionManager); for (UserAdmin userAdmin : userAdmins.values()) { - if (userAdmin instanceof AbstractUserDirectory) - ((AbstractUserDirectory) userAdmin) + if (userAdmin instanceof UserDirectory) + ((UserDirectory) userAdmin) .setTransactionManager(transactionManager); } } diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java index f68940002..18cb5ece2 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java @@ -41,7 +41,7 @@ import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.User; import org.osgi.service.useradmin.UserAdmin; -public abstract class AbstractUserDirectory implements UserAdmin { +abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { private final static Log log = LogFactory .getLog(AbstractUserDirectory.class); @@ -72,7 +72,7 @@ public abstract class AbstractUserDirectory implements UserAdmin { // TODO make a copy? this.properties = properties; - String uriStr = LdapProperties.uri.getValue(properties); + String uriStr = UserAdminProps.uri.getValue(properties); if (uriStr == null) uri = null; else @@ -82,16 +82,16 @@ public abstract class AbstractUserDirectory implements UserAdmin { throw new UserDirectoryException("Badly formatted URI", e); } - baseDn = LdapProperties.baseDn.getValue(properties).toString(); - String isReadOnly = LdapProperties.readOnly.getValue(properties); + baseDn = UserAdminProps.baseDn.getValue(properties).toString(); + String isReadOnly = UserAdminProps.readOnly.getValue(properties); if (isReadOnly == null) this.isReadOnly = readOnlyDefault(uri); else this.isReadOnly = new Boolean(isReadOnly); - this.userObjectClass = LdapProperties.userObjectClass + this.userObjectClass = UserAdminProps.userObjectClass .getValue(properties); - this.groupObjectClass = LdapProperties.groupObjectClass + this.groupObjectClass = UserAdminProps.groupObjectClass .getValue(properties); } @@ -411,7 +411,7 @@ public abstract class AbstractUserDirectory implements UserAdmin { return groupObjectClass; } - protected Dictionary getProperties() { + public Dictionary getProperties() { return properties; } 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 index 750d6a82a..830488589 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java @@ -48,8 +48,8 @@ public class LdifUserAdmin extends AbstractUserDirectory { private static Dictionary fromUri(String uri, String baseDn) { Hashtable res = new Hashtable(); - res.put(LdapProperties.uri.getFullName(), uri); - res.put(LdapProperties.baseDn.getFullName(), baseDn); + res.put(UserAdminProps.uri.getFullName(), uri); + res.put(UserAdminProps.baseDn.getFullName(), baseDn); return res; } diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapProperties.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserAdminProps.java similarity index 67% rename from org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapProperties.java rename to org.argeo.security.core/src/org/argeo/osgi/useradmin/UserAdminProps.java index 749c8fe84..580110d72 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapProperties.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserAdminProps.java @@ -2,8 +2,10 @@ package org.argeo.osgi.useradmin; import java.io.UnsupportedEncodingException; import java.net.URI; +import java.net.URISyntaxException; import java.net.URLDecoder; import java.util.Dictionary; +import java.util.Enumeration; import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.LinkedList; @@ -12,7 +14,7 @@ import java.util.Map; import javax.naming.Context; -public enum LdapProperties { +public enum UserAdminProps { /** Base DN */ baseDn("dc=example,dc=com"), @@ -22,18 +24,24 @@ public enum LdapProperties { /** User objectClass */ userObjectClass("inetOrgPerson"), + /** Relative base DN for users */ + userBase("ou=users"), + /** Groups objectClass */ groupObjectClass("groupOfNames"), + /** Relative base DN for users */ + groupBase("ou=groups"), + /** Read-only source */ readOnly(null); - private static String PREFIX = "argeo.ldap."; + private static String PREFIX = "argeo.useradmin"; /** The default value. */ private Object def; - LdapProperties(Object def) { + UserAdminProps(Object def) { this.def = def; } @@ -64,6 +72,35 @@ public enum LdapProperties { return (T) res; } + /** Hides host and credentials. */ + public static URI propertiesAsUri(Dictionary properties) { + StringBuilder query = new StringBuilder(); + + boolean first = true; + for (Enumeration keys = properties.keys(); keys + .hasMoreElements();) { + String key = keys.nextElement(); + if (key.startsWith(PREFIX) && !key.equals(baseDn.getFullName()) + && !key.equals(uri.getFullName())) { + if (first) + first = false; + else + query.append('&'); + query.append(key.substring(PREFIX.length())); + query.append('=').append(properties.get(key).toString()); + } + } + + String bDn = (String) properties.get(baseDn.getFullName()); + try { + return new URI(null, null, bDn != null ? '/' + bDn : null, + query.length() != 0 ? query.toString() : null, null); + } catch (URISyntaxException e) { + throw new UserDirectoryException( + "Cannot create URI from properties", e); + } + } + public static Dictionary uriAsProperties(String uriStr) { try { Hashtable res = new Hashtable(); @@ -72,6 +109,9 @@ public enum LdapProperties { String path = u.getPath(); String bDn = path.substring(path.lastIndexOf('/') + 1, path.length()); + if (bDn.endsWith(".ldif")) + bDn = bDn.substring(0, bDn.length() - ".ldif".length()); + String principal = null; String credentials = null; if (scheme != null) @@ -81,15 +121,12 @@ public enum LdapProperties { principal = userInfo.length > 0 ? userInfo[0] : null; credentials = userInfo.length > 1 ? userInfo[1] : null; } else if (scheme.equals("file")) { - if (bDn.endsWith(".ldif")) { - bDn = bDn.substring(0, bDn.length() - ".ldif".length()); - } } else throw new UserDirectoryException("Unsupported scheme " + scheme); Map> query = splitQuery(u.getQuery()); for (String key : query.keySet()) { - LdapProperties ldapProp = LdapProperties.valueOf(key); + UserAdminProps ldapProp = UserAdminProps.valueOf(key); List values = query.get(key); if (values.size() == 1) { res.put(ldapProp.getFullName(), values.get(0)); @@ -115,7 +152,7 @@ public enum LdapProperties { } } - public static Map> splitQuery(String query) + private static Map> splitQuery(String query) throws UnsupportedEncodingException { final Map> query_pairs = new LinkedHashMap>(); if (query == null) @@ -136,13 +173,19 @@ public enum LdapProperties { } public static void main(String[] args) { - System.out.println(uriAsProperties("ldap://" + Dictionary props = uriAsProperties("ldap://" + "uid=admin,ou=system:secret@localhost:10389" + "/dc=example,dc=com" - + "?readOnly=false&userObjectClass=person")); + + "?readOnly=false&userObjectClass=person"); + System.out.println(props); + System.out.println(propertiesAsUri(props)); + System.out .println(uriAsProperties("file://some/dir/dc=example,dc=com.ldif")); - System.out - .println(uriAsProperties("/dc=example,dc=com.ldif?readOnly=true")); + + props = uriAsProperties("/dc=example,dc=com.ldif?readOnly=true" + + "&userBase=ou=CoWorkers,ou=People&groupBase=ou=Roles"); + System.out.println(props); + System.out.println(propertiesAsUri(props)); } } diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserDirectory.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserDirectory.java new file mode 100644 index 000000000..b02acd666 --- /dev/null +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserDirectory.java @@ -0,0 +1,23 @@ +package org.argeo.osgi.useradmin; + +import java.util.Dictionary; + +import javax.transaction.TransactionManager; + +import org.osgi.service.useradmin.UserAdmin; + +/** Information about a user directory. */ +public interface UserDirectory { + public String getBaseDn(); + + public void setExternalRoles(UserAdmin externalRoles); + + public Dictionary getProperties(); + + // Transitional. In the future, more will be managed in OSGi. + public void setTransactionManager(TransactionManager transactionManager); + + public void init(); + + public void destroy(); +} -- 2.30.2