// Node Security
/** URI to an LDIF file used as initialization or backend */
final static String USERADMIN_URI = "argeo.node.useradmin.uri";
+ final static String ROLES_BASEDN = "ou=system,ou=node";
final static String[] DEFAULT_CNDS = { "/org/argeo/jcr/argeo.cnd",
"/org/argeo/cms/cms.cnd" };
package org.argeo.cms.internal.kernel;
+import java.io.File;
+import java.io.IOException;
+
import javax.jcr.RepositoryException;
+import org.apache.commons.io.FileUtils;
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.cms.internal.useradmin.SimpleJcrSecurityModel;
import org.argeo.cms.internal.useradmin.jackrabbit.JackrabbitUserAdminService;
import org.argeo.osgi.useradmin.AbstractLdapUserAdmin;
import org.argeo.security.core.OsAuthenticationProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.UserAdmin;
import org.springframework.security.authentication.AnonymousAuthenticationProvider;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
private final InternalAuthenticationProvider internalAuth;
private final AnonymousAuthenticationProvider anonymousAuth;
private final JackrabbitUserAdminService userAdminService;
- private final AbstractLdapUserAdmin userAdmin;
+ private final NodeUserAdmin userAdmin;
private ServiceRegistration<AuthenticationManager> authenticationManagerReg;
private ServiceRegistration<UserAdminService> userAdminServiceReg;
userAdminService.setSecurityModel(new SimpleJcrSecurityModel());
userAdminService.init();
+ userAdmin = new NodeUserAdmin();
+
+ String baseDn = "dc=example,dc=com";
String userAdminUri = KernelUtils
.getFrameworkProp(KernelConstants.USERADMIN_URI);
if (userAdminUri == null)
- userAdminUri = getClass().getResource("demo.ldif").toString();
+ userAdminUri = getClass().getResource(baseDn + ".ldif").toString();
+ AbstractLdapUserAdmin businessRoles;
if (userAdminUri.startsWith("ldap"))
- userAdmin = new LdapUserAdmin(userAdminUri);
- else
- userAdmin = new LdifUserAdmin(userAdminUri);
+ businessRoles = new LdapUserAdmin(userAdminUri);
+ else {
+ businessRoles = new LdifUserAdmin(userAdminUri);
+ }
+ businessRoles.init();
+ userAdmin.addUserAdmin(baseDn, businessRoles);
+
+ File osgiInstanceDir = KernelUtils.getOsgiInstanceDir();
+ File homeDir = new File(osgiInstanceDir, "node");
+
+ String baseNodeRoleDn = KernelConstants.ROLES_BASEDN;
+ File nodeRolesFile = new File(homeDir, baseNodeRoleDn + ".ldif");
+ try {
+ FileUtils.copyInputStreamToFile(
+ getClass().getResourceAsStream("demo.ldif"), nodeRolesFile);
+ } catch (IOException e) {
+ throw new CmsException("Cannot copy demo resource", e);
+ }
+ LdifUserAdmin nodeRoles = new LdifUserAdmin(nodeRolesFile.toURI()
+ .toString());
+ nodeRoles.setExternalRoles(userAdmin);
+ nodeRoles.init();
+ // nodeRoles.createRole(KernelHeader.ROLE_ADMIN, Role.GROUP);
+ userAdmin.addUserAdmin(baseNodeRoleDn, nodeRoles);
+
}
public void publish() {
userAdminServiceReg.unregister();
authenticationManagerReg.unregister();
- userAdmin.destroy();
+ // userAdmin.destroy();
userAdminReg.unregister();
}
--- /dev/null
+package org.argeo.cms.internal.kernel;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.osgi.useradmin.ArgeoUserAdminException;
+import org.argeo.osgi.useradmin.UserAdminAggregator;
+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 NodeUserAdmin implements UserAdmin, UserAdminAggregator {
+ final static LdapName ROLES_BASE;
+ static {
+ try {
+ ROLES_BASE = new LdapName(KernelConstants.ROLES_BASEDN);
+ } catch (InvalidNameException e) {
+ throw new ArgeoUserAdminException("Cannot initialize "
+ + NodeUserAdmin.class, e);
+ }
+ }
+
+ private UserAdmin nodeRoles = null;
+ private Map<LdapName, UserAdmin> userAdmins = new HashMap<LdapName, UserAdmin>();
+
+ @Override
+ public Role createRole(String name, int type) {
+ return findUserAdmin(name).createRole(name, type);
+ }
+
+ @Override
+ public boolean removeRole(String name) {
+ return findUserAdmin(name).removeRole(name);
+ }
+
+ @Override
+ public Role getRole(String name) {
+ return findUserAdmin(name).getRole(name);
+ }
+
+ @Override
+ public Role[] getRoles(String filter) throws InvalidSyntaxException {
+ List<Role> res = new ArrayList<Role>();
+ for (UserAdmin userAdmin : userAdmins.values()) {
+ res.addAll(Arrays.asList(userAdmin.getRoles(filter)));
+ }
+ res.addAll(Arrays.asList(nodeRoles.getRoles(filter)));
+ return res.toArray(new Role[res.size()]);
+ }
+
+ @Override
+ public User getUser(String key, String value) {
+ List<User> res = new ArrayList<User>();
+ for (UserAdmin userAdmin : userAdmins.values()) {
+ User u = userAdmin.getUser(key, value);
+ if (u != null)
+ res.add(u);
+ }
+ // Note: node roles cannot contain users, so it is not searched
+ return res.size() == 1 ? res.get(0) : null;
+ }
+
+ @Override
+ public Authorization getAuthorization(User user) {
+ UserAdmin userAdmin = findUserAdmin(user.getName());
+ // FIXME clarify assumptions
+ return userAdmin.getAuthorization(user);
+ // String[] roles = auth.getRoles();
+ // // Gather system roles
+ // Set<String> systemRoles = new HashSet<String>();
+ // for(String businessRole:roles){
+ //
+ // }
+ // return null;
+ }
+
+ //
+ // USER ADMIN AGGREGATOR
+ //
+ @Override
+ public synchronized void addUserAdmin(String baseDn, UserAdmin userAdmin) {
+ if (baseDn.equals(KernelConstants.ROLES_BASEDN)) {
+ nodeRoles = userAdmin;
+ return;
+ }
+
+ if (userAdmins.containsKey(baseDn))
+ throw new ArgeoUserAdminException(
+ "There is already a user admin for " + baseDn);
+ try {
+ userAdmins.put(new LdapName(baseDn), userAdmin);
+ } catch (InvalidNameException e) {
+ throw new ArgeoUserAdminException("Badly formatted base DN "
+ + baseDn, e);
+ }
+ }
+
+ @Override
+ public synchronized void removeUserAdmin(String baseDn) {
+ if (baseDn.equals(KernelConstants.ROLES_BASEDN))
+ throw new ArgeoUserAdminException("Node roles cannot be removed.");
+ LdapName base;
+ try {
+ base = new LdapName(baseDn);
+ } catch (InvalidNameException e) {
+ throw new ArgeoUserAdminException("Badly formatted base DN "
+ + baseDn, e);
+ }
+ if (!userAdmins.containsKey(base))
+ throw new ArgeoUserAdminException("There is no user admin for "
+ + base);
+ userAdmins.remove(base);
+ }
+
+ private UserAdmin findUserAdmin(String name) {
+ try {
+ return findUserAdmin(new LdapName(name));
+ } catch (InvalidNameException e) {
+ throw new ArgeoUserAdminException("Badly formatted name " + name, e);
+ }
+ }
+
+ private UserAdmin findUserAdmin(LdapName name) {
+ if (name.startsWith(ROLES_BASE))
+ return nodeRoles;
+ List<UserAdmin> res = new ArrayList<UserAdmin>(1);
+ for (LdapName baseDn : userAdmins.keySet()) {
+ if (name.startsWith(baseDn))
+ res.add(userAdmins.get(baseDn));
+ }
+ if (res.size() == 0)
+ throw new ArgeoUserAdminException("Cannot find user admin for "
+ + name);
+ if (res.size() > 1)
+ throw new ArgeoUserAdminException("Multiple user admin found for "
+ + name);
+ return res.get(0);
+ }
+}
--- /dev/null
+dn: dc=example,dc=com
+objectClass: domain
+objectClass: extensibleObject
+objectClass: top
+dc: example
+
+dn: ou=groups,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: top
+ou: groups
+
+dn: ou=users,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: top
+ou: users
+
+dn: uid=demo,ou=users,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+cn: Demo User
+description: Demo user
+givenname: Demo
+mail: demo@localhost
+sn: User
+uid: demo
+userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9
+
+dn: uid=root,ou=users,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: person
+objectClass: organizationalPerson
+objectClass: top
+cn: Super User
+description: Superuser
+givenname: Super
+mail: root@localhost
+sn: User
+uid: root
+userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9
-dn: dc=example,dc=com
-objectClass: domain
-objectClass: extensibleObject
-objectClass: top
-dc: example
-
-dn: ou=groups,dc=example,dc=com
-objectClass: organizationalUnit
-objectClass: top
-ou: groups
-
-dn: ou=users,dc=example,dc=com
-objectClass: organizationalUnit
-objectClass: top
-ou: users
-
-dn: uid=demo,ou=users,dc=example,dc=com
-objectClass: inetOrgPerson
-objectClass: organizationalPerson
-objectClass: person
-objectClass: top
-cn: Demo User
-description: Demo user
-givenname: Demo
-mail: demo@localhost
-sn: User
-uid: demo
-userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9
-
-dn: uid=root,ou=users,dc=example,dc=com
-objectClass: inetOrgPerson
-objectClass: person
-objectClass: organizationalPerson
-objectClass: top
-cn: Super User
-description: Superuser
-givenname: Super
-mail: root@localhost
-sn: User
-uid: root
-userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9
-
dn: ou=node
objectClass: organizationalUnit
objectClass: top