From: Mathieu Baudier Date: Wed, 26 Aug 2015 12:59:10 +0000 (+0000) Subject: Introduce Argeo 2 security model- X-Git-Tag: argeo-commons-2.1.30~187 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=93a457cf047cebb0170abd0f37a9b4291a2ae3e9;p=lgpl%2Fargeo-commons.git Introduce Argeo 2 security model- git-svn-id: https://svn.argeo.org/commons/trunk@8346 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/demo/log4j.properties b/demo/log4j.properties index 8b071c036..1238aeebe 100644 --- a/demo/log4j.properties +++ b/demo/log4j.properties @@ -1,6 +1,7 @@ log4j.rootLogger=WARN, development log4j.logger.org.argeo=DEBUG +log4j.logger.org.apache.jackrabbit.core.RepositoryImpl=DEBUG #log4j.logger.argeo.stats=DEBUG ## Appenders diff --git a/org.argeo.cms/src/org/argeo/cms/AbstractCmsEntryPoint.java b/org.argeo.cms/src/org/argeo/cms/AbstractCmsEntryPoint.java index 00db13443..951e177b2 100644 --- a/org.argeo.cms/src/org/argeo/cms/AbstractCmsEntryPoint.java +++ b/org.argeo.cms/src/org/argeo/cms/AbstractCmsEntryPoint.java @@ -1,5 +1,6 @@ package org.argeo.cms; +import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -103,14 +104,20 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint } @Override - protected final void createContents(Composite parent) { - try { - getShell().getDisplay().setData(CmsSession.KEY, this); - - createUi(parent); - } catch (Exception e) { - throw new CmsException("Cannot create entrypoint contents", e); - } + protected final void createContents(final Composite parent) { + getShell().getDisplay().setData(CmsSession.KEY, this); + Subject.doAs(subject, new PrivilegedAction() { + @Override + public Void run() { + try { + createUi(parent); + } catch (Exception e) { + throw new CmsException("Cannot create entrypoint contents", + e); + } + return null; + } + }); } /** Create UI */ @@ -140,7 +147,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint public void navigateTo(String state) { exception = null; String title = setState(state); - refresh(); + doRefresh(); if (browserNavigation != null) browserNavigation.pushState(state, title); } @@ -152,48 +159,66 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint @Override public void authChange() { - try { - String currentPath = null; - if (node != null) - currentPath = node.getPath(); - JcrUtils.logoutQuietly(session); + Subject.doAs(subject, new PrivilegedAction() { - session = repository.login(workspace); - if (currentPath != null) + @Override + public Void run() { try { - node = session.getNode(currentPath); - } catch (Exception e) { - try { - // TODO find a less hacky way to log out - new ArgeoLoginContext( - KernelHeader.LOGIN_CONTEXT_ANONYMOUS, subject) - .logout(); - new ArgeoLoginContext( - KernelHeader.LOGIN_CONTEXT_ANONYMOUS, subject) - .login(); - } catch (LoginException eAnonymous) { - throw new ArgeoException("Cannot reset to anonymous", - eAnonymous); - } + String currentPath = null; + if (node != null) + currentPath = node.getPath(); JcrUtils.logoutQuietly(session); + session = repository.login(workspace); - navigateTo("~"); - throw e; + if (currentPath != null) + try { + node = session.getNode(currentPath); + } catch (Exception e) { + try { + // TODO find a less hacky way to log out + new ArgeoLoginContext( + KernelHeader.LOGIN_CONTEXT_ANONYMOUS, + subject).logout(); + new ArgeoLoginContext( + KernelHeader.LOGIN_CONTEXT_ANONYMOUS, + subject).login(); + } catch (LoginException eAnonymous) { + throw new ArgeoException( + "Cannot reset to anonymous", eAnonymous); + } + JcrUtils.logoutQuietly(session); + session = repository.login(workspace); + navigateTo("~"); + throw e; + } + + // refresh UI + doRefresh(); + } catch (RepositoryException e) { + throw new CmsException("Cannot perform auth change", e); } + return null; + } - // refresh UI - refresh(); - } catch (RepositoryException e) { - throw new CmsException("Cannot perform auth change", e); - } + }); } @Override - public void exception(Throwable e) { - this.exception = e; + public void exception(final Throwable e) { + AbstractCmsEntryPoint.this.exception = e; log.error("Unexpected exception in CMS", e); - refresh(); + doRefresh(); + } + + protected void doRefresh() { + Subject.doAs(subject, new PrivilegedAction() { + @Override + public Void run() { + refresh(); + return null; + } + }); } @Override diff --git a/org.argeo.cms/src/org/argeo/cms/KernelHeader.java b/org.argeo.cms/src/org/argeo/cms/KernelHeader.java index c2dd2cae7..620699abf 100644 --- a/org.argeo.cms/src/org/argeo/cms/KernelHeader.java +++ b/org.argeo.cms/src/org/argeo/cms/KernelHeader.java @@ -9,14 +9,17 @@ public interface KernelHeader { final static String LOGIN_CONTEXT_SINGLE_USER = "SINGLE_USER"; // RESERVED ROLES - public final static String ROLE_ADMIN = "ROLE_ADMIN"; - public final static String ROLE_GROUP_ADMIN = "ROLE_GROUP_ADMIN"; - public final static String ROLE_USER_ADMIN = "ROLE_USER_ADMIN"; - public final static String ROLE_USER = "ROLE_USER"; - public final static String ROLE_ANONYMOUS = "ROLE_ANONYMOUS"; + public final static String ROLE_ADMIN = "cn=admin,ou=system,ou=node"; + public final static String ROLE_GROUP_ADMIN = "cn=groupAdmin,ou=system,ou=node"; + public final static String ROLE_USER_ADMIN = "cn=userAdmin,ou=system,ou=node"; + // Special system groups that cannot be edited: + // user U anonymous = everyone + public final static String ROLE_USER = "cn=user,ou=system,ou=node"; + public final static String ROLE_ANONYMOUS = "cn=anonymous,ou=system,ou=node"; // RESERVED USERNAMES public final static String USERNAME_ADMIN = "root"; public final static String USERNAME_DEMO = "demo"; + @Deprecated public final static String USERNAME_ANONYMOUS = "anonymous"; } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/auth/ImpliedByPrincipal.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/ImpliedByPrincipal.java new file mode 100644 index 000000000..417ea69ce --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/ImpliedByPrincipal.java @@ -0,0 +1,90 @@ +package org.argeo.cms.internal.auth; + +import java.security.Principal; +import java.security.acl.Group; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; + +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; + +import org.argeo.cms.CmsException; +import org.osgi.service.useradmin.Authorization; + +/** + * A {@link Principal} which has been implied by an {@link Authorization}. If it + * is empty it meeans this is an additional identity, otherwise it lists the + * users (typically the logged in user but possibly empty + * {@link ImpliedByPrincipal}s) which have implied it. When an additional + * identityx is removed, the related {@link ImpliedByPrincipal}s can thus be + * removed. + */ +public final class ImpliedByPrincipal implements Group { + private final LdapName name; + private Set causes = new HashSet(); + + public ImpliedByPrincipal(String name, Principal userPrincipal) { + try { + this.name = new LdapName(name); + } catch (InvalidNameException e) { + throw new CmsException("Badly formatted role name", e); + } + if (userPrincipal != null) + causes.add(userPrincipal); + } + + public ImpliedByPrincipal(LdapName name, Principal userPrincipal) { + this.name = name; + if (userPrincipal != null) + causes.add(userPrincipal); + } + + @Override + public String getName() { + return name.toString(); + } + + @Override + public boolean addMember(Principal user) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeMember(Principal user) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isMember(Principal member) { + return causes.contains(member); + } + + @Override + public Enumeration members() { + return Collections.enumeration(causes); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + // if (this == obj) + // return true; + if (obj instanceof ImpliedByPrincipal) { + ImpliedByPrincipal that = (ImpliedByPrincipal) obj; + // TODO check members too? + return name.equals(that.name); + } + return false; + } + + @Override + public String toString() { + return name.toString() + ", implied by " + causes; + } +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/auth/UserAdminLoginModule.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/UserAdminLoginModule.java new file mode 100644 index 000000000..dea6048e6 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/UserAdminLoginModule.java @@ -0,0 +1,199 @@ +package org.argeo.cms.internal.auth; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.security.Principal; +import java.util.Arrays; +import java.util.Map; +import java.util.Set; + +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.login.CredentialNotFoundException; +import javax.security.auth.login.LoginException; +import javax.security.auth.spi.LoginModule; +import javax.security.auth.x500.X500Principal; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; +import org.argeo.cms.CmsException; +import org.argeo.cms.KernelHeader; +import org.argeo.cms.internal.kernel.Activator; +import org.osgi.framework.BundleContext; +import org.osgi.service.useradmin.Authorization; +import org.osgi.service.useradmin.User; +import org.osgi.service.useradmin.UserAdmin; + +public class UserAdminLoginModule implements LoginModule { + private Subject subject; + private CallbackHandler callbackHandler; + private boolean isAnonymous = false; + + private final static LdapName ROLE_USER_NAME, ROLE_ANONYMOUS_NAME; + private final static X500Principal ROLE_ANONYMOUS_PRINCIPAL; + static { + try { + ROLE_USER_NAME = new LdapName(KernelHeader.ROLE_USER); + ROLE_ANONYMOUS_NAME = new LdapName(KernelHeader.ROLE_ANONYMOUS); + ROLE_ANONYMOUS_PRINCIPAL = new X500Principal( + ROLE_ANONYMOUS_NAME.toString()); + } catch (InvalidNameException e) { + throw new Error("Cannot initialize login module class", e); + } + } + + private Authorization authorization; + + @Override + public void initialize(Subject subject, CallbackHandler callbackHandler, + Map sharedState, Map options) { + try { + this.subject = subject; + this.callbackHandler = callbackHandler; + if (options.containsKey("anonymous")) + isAnonymous = Boolean.parseBoolean(options.get("anonymous") + .toString()); + // String ldifFile = options.get("ldifFile").toString(); + // InputStream in = new URL(ldifFile).openStream(); + // userAdmin = new LdifUserAdmin(in); + } catch (Exception e) { + throw new CmsException("Cannot initialize login module", e); + } + } + + @Override + public boolean login() throws LoginException { + // TODO use a callback in order to get the bundle context + BundleContext bc = Activator.getBundleContext(); + UserAdmin userAdmin = bc.getService(bc + .getServiceReference(UserAdmin.class)); + final User user; + + if (!isAnonymous) { + // ask for username and password + NameCallback nameCallback = new NameCallback("User"); + PasswordCallback passwordCallback = new PasswordCallback( + "Password", false); + // handle callbacks + try { + callbackHandler.handle(new Callback[] { nameCallback, + passwordCallback }); + } catch (Exception e) { + throw new CmsException("Cannot handle callbacks", e); + } + + // create credentials + final String username = nameCallback.getName(); + if (username == null || username.trim().equals("")) + throw new CredentialNotFoundException("No credentials provided"); + + char[] password = {}; + if (passwordCallback.getPassword() != null) + password = passwordCallback.getPassword(); + else + throw new CredentialNotFoundException("No credentials provided"); + + user = (User) userAdmin.getRole(username); + if (user == null) + return false; + + byte[] hashedPassword = ("{SHA}" + Base64 + .encodeBase64String(DigestUtils.sha1(toBytes(password)))) + .getBytes(); + if (!user.hasCredential("userpassword", hashedPassword)) + return false; + } else + // anonymous + user = null; + this.authorization = userAdmin.getAuthorization(user); + return true; + } + + private byte[] toBytes(char[] chars) { + CharBuffer charBuffer = CharBuffer.wrap(chars); + ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer); + byte[] bytes = Arrays.copyOfRange(byteBuffer.array(), + byteBuffer.position(), byteBuffer.limit()); + Arrays.fill(charBuffer.array(), '\u0000'); // clear sensitive data + Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data + return bytes; + } + + @Override + public boolean commit() throws LoginException { + if (authorization != null) { + Set principals = subject.getPrincipals(); + try { + String authName = authorization.getName(); + + // determine user'S principal + final LdapName name; + final Principal userPrincipal; + if (authName == null) { + name = ROLE_ANONYMOUS_NAME; + userPrincipal = ROLE_ANONYMOUS_PRINCIPAL; + principals.add(userPrincipal); + } else { + name = new LdapName(authName); + userPrincipal = new X500Principal(name.toString()); + principals.add(userPrincipal); + principals.add(new ImpliedByPrincipal(ROLE_USER_NAME, + userPrincipal)); + } + + // Add roles provided by authorization + for (String role : authorization.getRoles()) { + LdapName roleName = new LdapName(role); + if (ROLE_USER_NAME.equals(roleName)) + throw new CmsException(ROLE_USER_NAME + + " cannot be listed as role"); + if (ROLE_ANONYMOUS_NAME.equals(roleName)) + throw new CmsException(ROLE_ANONYMOUS_NAME + + " cannot be listed as role"); + if (roleName.equals(name)) { + // skip + } else { + principals.add(new ImpliedByPrincipal(roleName + .toString(), userPrincipal)); + } + } + + return true; + } catch (InvalidNameException e) { + throw new CmsException("Cannot commit", e); + } + } else + return false; + } + + @Override + public boolean abort() throws LoginException { + cleanUp(); + return true; + } + + @Override + public boolean logout() throws LoginException { + // TODO better deal with successive logout + if (subject == null) + return true; + // TODO make it less brutal + subject.getPrincipals().removeAll( + subject.getPrincipals(X500Principal.class)); + subject.getPrincipals().removeAll( + subject.getPrincipals(ImpliedByPrincipal.class)); + cleanUp(); + return true; + } + + private void cleanUp() { + subject = null; + authorization = null; + } +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java index af4f0ff2a..83f21202e 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java @@ -1,6 +1,7 @@ package org.argeo.cms.internal.kernel; import java.lang.management.ManagementFactory; +import java.net.URL; import java.util.HashMap; import java.util.Map; @@ -47,6 +48,11 @@ final class Kernel implements ServiceListener { private KernelThread kernelThread; void init() { + URL url = getClass().getClassLoader().getResource( + KernelConstants.JAAS_CONFIG); + System.setProperty("java.security.auth.login.config", + url.toExternalForm()); + ClassLoader currentContextCl = Thread.currentThread() .getContextClassLoader(); Thread.currentThread().setContextClassLoader( 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 7465583f9..f273242c5 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 @@ -16,6 +16,10 @@ public interface KernelConstants { final static String REPO_SEARCH_CACHE_SIZE = "argeo.node.repo.searchCacheSize"; final static String REPO_MAX_VOLATILE_INDEX_SIZE = "argeo.node.repo.maxVolatileIndexSize"; + // Node Security + /** URI to an LDIF file used as initialization or backend */ + final static String USERADMIN_URI = "argeo.node.useradmin.uri"; + 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 f279ba5ea..3b5d78d89 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 @@ -10,6 +10,7 @@ import org.argeo.cms.CmsException; import org.argeo.cms.internal.useradmin.JcrUserAdmin; import org.argeo.cms.internal.useradmin.SimpleJcrSecurityModel; import org.argeo.cms.internal.useradmin.jackrabbit.JackrabbitUserAdminService; +import org.argeo.osgi.useradmin.LdifUserAdmin; import org.argeo.security.OsAuthenticationToken; import org.argeo.security.UserAdminService; import org.argeo.security.core.InternalAuthentication; @@ -36,7 +37,7 @@ class NodeSecurity implements AuthenticationManager { private final InternalAuthenticationProvider internalAuth; private final AnonymousAuthenticationProvider anonymousAuth; private final JackrabbitUserAdminService userAdminService; - private final JcrUserAdmin userAdmin; + private final LdifUserAdmin userAdmin; private ServiceRegistration authenticationManagerReg; private ServiceRegistration userAdminServiceReg; @@ -46,11 +47,6 @@ class NodeSecurity implements AuthenticationManager { public NodeSecurity(BundleContext bundleContext, JackrabbitNode node) throws RepositoryException { - URL url = getClass().getClassLoader().getResource( - KernelConstants.JAAS_CONFIG); - System.setProperty("java.security.auth.login.config", - url.toExternalForm()); - this.bundleContext = bundleContext; osAuth = new OsAuthenticationProvider(); @@ -65,8 +61,11 @@ class NodeSecurity implements AuthenticationManager { userAdminService.setSecurityModel(new SimpleJcrSecurityModel()); userAdminService.init(); - userAdmin = new JcrUserAdmin(bundleContext, node); - userAdmin.setUserAdminService(userAdminService); + String userAdminUri = KernelUtils + .getFrameworkProp(KernelConstants.USERADMIN_URI); + if (userAdminUri == null) + userAdminUri = getClass().getResource("demo.ldif").toString(); + userAdmin = new LdifUserAdmin(userAdminUri); } public void publish() { diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/demo.ldif b/org.argeo.cms/src/org/argeo/cms/internal/kernel/demo.ldif new file mode 100644 index 000000000..980719fc3 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/demo.ldif @@ -0,0 +1,68 @@ +dn: dc=example,dc=org +objectClass: domain +objectClass: extensibleObject +objectClass: top +dc: example + +dn: ou=groups,dc=example,dc=org +objectClass: organizationalUnit +objectClass: top +ou: groups + +dn: ou=users,dc=example,dc=org +objectClass: organizationalUnit +objectClass: top +ou: users + +dn: uid=demo,ou=users,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,ou=users,dc=example,dc=org +objectClass: person +objectClass: inetOrgPerson +objectClass: organizationalPerson +objectClass: top +cn: Super User +description: Superuser +givenname: Super +mail: root@localhost +sn: User +uid: root +userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9 + +dn: cn=admin,ou=system,ou=node +objectClass: groupOfNames +objectClass: top +cn: admin +member: uid=root,ou=users,dc=example,dc=org + +dn: cn=userAdmin,ou=system,ou=node +objectClass: groupOfNames +objectClass: top +cn: userAdmin +member: cn=admin,ou=system,ou=node +member: uid=demo,ou=users,dc=example,dc=org + +dn: cn=groupAdmin,ou=system,ou=node +objectClass: groupOfNames +objectClass: top +cn: groupAdmin +member: cn=admin,ou=system,ou=node + +dn: cn=editor,ou=cms,ou=node +objectClass: groupOfNames +objectClass: top +cn: admin +member: cn=admin,ou=system,ou=node +member: uid=demo,ou=users,dc=example,dc=org + diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg index c8033b1bd..0e76f376a 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg @@ -1,14 +1,28 @@ USER { + org.argeo.cms.internal.auth.UserAdminLoginModule requisite; +}; + +OLD_USER { org.argeo.cms.internal.auth.EndUserLoginModule requisite; org.springframework.security.authentication.jaas.SecurityContextLoginModule requisite; }; ANONYMOUS { + org.argeo.cms.internal.auth.UserAdminLoginModule requisite anonymous=true; +}; + +OLD_ANONYMOUS { org.argeo.cms.internal.auth.AnonymousLoginModule requisite; org.springframework.security.authentication.jaas.SecurityContextLoginModule requisite; }; SYSTEM { + org.argeo.cms.internal.auth.SystemLoginModule requisite; + org.springframework.security.authentication.jaas.SecurityContextLoginModule requisite; + org.argeo.security.jackrabbit.SystemJackrabbitLoginModule requisite; +}; + +OLD_SYSTEM { org.argeo.cms.internal.auth.SystemLoginModule requisite; org.springframework.security.authentication.jaas.SecurityContextLoginModule requisite; }; @@ -22,3 +36,8 @@ SINGLE_USER { org.argeo.cms.internal.auth.SingleUserLoginModule requisite; org.springframework.security.authentication.jaas.SecurityContextLoginModule requisite; }; + +Jackrabbit { + org.argeo.security.jackrabbit.SystemJackrabbitLoginModule requisite; +}; + diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/repository-h2.xml b/org.argeo.cms/src/org/argeo/cms/internal/kernel/repository-h2.xml index 4c4875f1c..981dff473 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/repository-h2.xml +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/repository-h2.xml @@ -76,7 +76,7 @@ - - + + \ No newline at end of file diff --git a/org.argeo.cms/src/org/argeo/cms/util/CurrentUserUtils.java b/org.argeo.cms/src/org/argeo/cms/util/CurrentUserUtils.java new file mode 100644 index 000000000..a47cad0e8 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/util/CurrentUserUtils.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.cms.util; + +import java.security.AccessController; +import java.security.Principal; +import java.security.acl.Group; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; + +import org.argeo.ArgeoException; +import org.argeo.cms.CmsSession; + +/** + * Retrieves information about the current user. Not an API, can change without + * notice. + */ +class CurrentUserUtils { + public final static String getUsername() { + Subject subject = getSubject(); + if (subject == null) + return null; + Principal principal = subject.getPrincipals(X500Principal.class) + .iterator().next(); + return principal.getName(); + + } + + public final static Set roles() { + Set roles = Collections.synchronizedSet(new HashSet()); + // roles.add("ROLE_USER"); + Subject subject = getSubject(); + X500Principal userPrincipal = subject + .getPrincipals(X500Principal.class).iterator().next(); + roles.add(userPrincipal.getName()); + for (Principal group : subject.getPrincipals(Group.class)) { + roles.add(group.getName()); + } + return roles; + } + + public final static Subject getSubject() { + Subject subject = Subject.getSubject(AccessController.getContext()); + if (subject == null) { + subject = CmsSession.current.get().getSubject(); + if (subject == null) + throw new ArgeoException("Not authenticated."); + } + return subject; + } +} diff --git a/org.argeo.cms/src/org/argeo/cms/util/UserMenu.java b/org.argeo.cms/src/org/argeo/cms/util/UserMenu.java index ad47d1850..1c3560001 100644 --- a/org.argeo.cms/src/org/argeo/cms/util/UserMenu.java +++ b/org.argeo.cms/src/org/argeo/cms/util/UserMenu.java @@ -32,8 +32,6 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; /** The site-related user menu */ public class UserMenu extends Shell implements CmsStyles, CallbackHandler { @@ -44,13 +42,13 @@ public class UserMenu extends Shell implements CmsStyles, CallbackHandler { super(source.getDisplay(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP); setData(RWT.CUSTOM_VARIANT, CMS_USER_MENU); - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); - if (authentication == null) - throw new CmsException("No authentication available"); + // Authentication authentication = SecurityContextHolder.getContext() + // .getAuthentication(); + // if (authentication == null) + // throw new CmsException("No authentication available"); - String username = authentication.getName(); - if (username.equals(KernelHeader.USERNAME_ANONYMOUS)) { + String username = CurrentUserUtils.getUsername(); + if (username.equalsIgnoreCase(KernelHeader.ROLE_ANONYMOUS)) { username = null; anonymousUi(); } else { @@ -107,11 +105,11 @@ public class UserMenu extends Shell implements CmsStyles, CallbackHandler { }); } - protected String getUsername() { - String username = SecurityContextHolder.getContext() - .getAuthentication().getName(); - return username; - } + // protected String getUsername() { + // // String username = SecurityContextHolder.getContext() + // // .getAuthentication().getName(); + // return CurrentUserUtils.getUsername(); + // } /** To be overridden */ protected void specificUserUi(Composite parent) { diff --git a/org.argeo.cms/src/org/argeo/cms/util/UserMenuLink.java b/org.argeo.cms/src/org/argeo/cms/util/UserMenuLink.java index 689318137..0dbb4ac5a 100644 --- a/org.argeo.cms/src/org/argeo/cms/util/UserMenuLink.java +++ b/org.argeo.cms/src/org/argeo/cms/util/UserMenuLink.java @@ -12,7 +12,6 @@ import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; -import org.springframework.security.core.context.SecurityContextHolder; /** Open the user menu when clicked */ public class UserMenuLink extends MenuLink { @@ -23,9 +22,10 @@ public class UserMenuLink extends MenuLink { @Override public Control createUi(Composite parent, Node context) { - String username = SecurityContextHolder.getContext() - .getAuthentication().getName(); - if (username.equals(KernelHeader.USERNAME_ANONYMOUS)) + // String username = SecurityContextHolder.getContext() + // .getAuthentication().getName(); + String username = CurrentUserUtils.getUsername(); + if (username.equalsIgnoreCase(KernelHeader.ROLE_ANONYMOUS)) setLabel(CmsMsg.login.lead()); else setLabel(username); diff --git a/org.argeo.eclipse.ui.workbench/plugin.xml b/org.argeo.eclipse.ui.workbench/plugin.xml index 5e281b29a..a4292c261 100644 --- a/org.argeo.eclipse.ui.workbench/plugin.xml +++ b/org.argeo.eclipse.ui.workbench/plugin.xml @@ -405,6 +405,7 @@ + + activityId="org.argeo.security.ui.adminActivity"> + activityId="org.argeo.security.ui.adminActivity"> \ No newline at end of file diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifAuthorization.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifAuthorization.java index 4ae2434b4..8f167c368 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifAuthorization.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifAuthorization.java @@ -15,6 +15,8 @@ public class LdifAuthorization implements Authorization { @Override public String getName() { + if (user == null) + return null; return user.getName(); } @@ -30,16 +32,20 @@ public class LdifAuthorization implements Authorization { @Override public String[] getRoles() { List allRoles = getAllRoles(); - String[] res = new String[allRoles.size() + 1]; - res[0] = user.getName(); + if (user != null) + allRoles.add(0, user); + String[] res = new String[allRoles.size()]; for (int i = 0; i < allRoles.size(); i++) - res[i + 1] = allRoles.get(i).getName(); + res[i] = allRoles.get(i).getName(); return res; } List getAllRoles() { List allRoles = new ArrayList(); - collectRoles(user, allRoles); + if (user != null) + collectRoles(user, allRoles); + else + collectAnonymousRoles(allRoles); return allRoles; } @@ -51,4 +57,8 @@ public class LdifAuthorization implements Authorization { } } + private void collectAnonymousRoles(List allRoles) { + // TODO gather anonymous roles + } + } 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 8cc7cb395..e2cf903fc 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 @@ -1,6 +1,8 @@ package org.argeo.osgi.useradmin; import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.util.SortedMap; import java.util.TreeMap; @@ -15,11 +17,44 @@ import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.User; import org.osgi.service.useradmin.UserAdmin; +/** User admin implementation using LDIF file(s) as backend. */ public class LdifUserAdmin implements UserAdmin { SortedMap users = new TreeMap(); SortedMap groups = new TreeMap(); + private final boolean isReadOnly; + private final URI uri; + + public LdifUserAdmin(String uri) { + this(uri, true); + } + + public LdifUserAdmin(String uri, boolean isReadOnly) { + this.isReadOnly = isReadOnly; + try { + this.uri = new URI(uri); + } catch (URISyntaxException e) { + throw new ArgeoUserAdminException("Invalid URI " + uri, e); + } + + if (!isReadOnly && !this.uri.getScheme().equals("file:")) + throw new UnsupportedOperationException(this.uri.getScheme() + + "not supported read-write."); + + try { + load(this.uri.toURL().openStream()); + } catch (Exception e) { + throw new ArgeoUserAdminException("Cannot open URL " + this.uri, e); + } + } + public LdifUserAdmin(InputStream in) { + load(in); + isReadOnly = true; + this.uri = null; + } + + protected void load(InputStream in) { try { LdifParser ldifParser = new LdifParser(); SortedMap allEntries = ldifParser.read(in); @@ -45,10 +80,17 @@ public class LdifUserAdmin implements UserAdmin { } } catch (Exception e) { throw new ArgeoUserAdminException( - "Cannot initialise user admin service from LDIF", e); + "Cannot load user admin service from LDIF", e); } } + public void destroy() { + users.clear(); + users = null; + groups.clear(); + groups = null; + } + @Override public Role getRole(String name) { LdapName key; @@ -92,4 +134,8 @@ public class LdifUserAdmin implements UserAdmin { throw new UnsupportedOperationException(); } + public boolean getIsReadOnly() { + return isReadOnly; + } + } diff --git a/org.argeo.security.jackrabbit/.classpath b/org.argeo.security.jackrabbit/.classpath index f9f1a39d8..f103f9cb1 100644 --- a/org.argeo.security.jackrabbit/.classpath +++ b/org.argeo.security.jackrabbit/.classpath @@ -1,9 +1,8 @@ - - - - + + + + + diff --git a/org.argeo.security.jackrabbit/build.properties b/org.argeo.security.jackrabbit/build.properties index 30f715358..8103225a3 100644 --- a/org.argeo.security.jackrabbit/build.properties +++ b/org.argeo.security.jackrabbit/build.properties @@ -1 +1,24 @@ -source.. = src/ +source.. = src/,\ + ext/test/ + +additional.bundles = org.junit,\ + org.apache.jackrabbit.core,\ + javax.jcr,\ + org.apache.jackrabbit.api,\ + org.apache.jackrabbit.data,\ + org.apache.jackrabbit.jcr.commons,\ + org.apache.jackrabbit.spi,\ + org.apache.jackrabbit.spi.commons,\ + org.slf4j.api,\ + org.slf4j.commons.logging,\ + org.slf4j.log4j12,\ + org.apache.log4j,\ + org.apache.commons.collections,\ + EDU.oswego.cs.dl.util.concurrent,\ + org.apache.lucene,\ + org.apache.tika.core,\ + org.apache.tika.parsers,\ + org.apache.commons.dbcp,\ + org.apache.commons.pool,\ + org.argeo.server.jcr + diff --git a/org.argeo.security.jackrabbit/ext/test/log4j.properties b/org.argeo.security.jackrabbit/ext/test/log4j.properties new file mode 100644 index 000000000..b4edd7c2e --- /dev/null +++ b/org.argeo.security.jackrabbit/ext/test/log4j.properties @@ -0,0 +1,17 @@ +log4j.rootLogger=WARN, console + +## Levels +log4j.logger.org.argeo=DEBUG +log4j.logger.org.apache.jackrabbit=OFF +log4j.logger.org.apache.jackrabbit.core.security=DEBUG +log4j.logger.org.apache.jackrabbit.core.DefaultSecurityManager=DEBUG + +## Appenders +# console is set to be a ConsoleAppender. +log4j.appender.console=org.apache.log4j.ConsoleAppender + +# console uses PatternLayout. +log4j.appender.console.layout=org.apache.log4j.PatternLayout +#log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n +#log4j.appender.console.layout.ConversionPattern=%m%n +log4j.appender.console.layout.ConversionPattern=%d{ABSOLUTE} %m (%F:%L) [%t] %p %n diff --git a/org.argeo.security.jackrabbit/ext/test/org/argeo/security/jackrabbit/JackrabbitAuthTest.java b/org.argeo.security.jackrabbit/ext/test/org/argeo/security/jackrabbit/JackrabbitAuthTest.java new file mode 100644 index 000000000..45a6567aa --- /dev/null +++ b/org.argeo.security.jackrabbit/ext/test/org/argeo/security/jackrabbit/JackrabbitAuthTest.java @@ -0,0 +1,42 @@ +package org.argeo.security.jackrabbit; + +import java.net.URL; + +import javax.jcr.Repository; +import javax.jcr.Session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.jackrabbit.unit.AbstractJackrabbitTestCase; + +public class JackrabbitAuthTest extends AbstractJackrabbitTestCase { + private final Log log = LogFactory.getLog(JackrabbitAuthTest.class); + + public void testLogin() throws Exception { + // Subject subject = new Subject(); + // LoginContext loginContext = new LoginContext("UNIX",subject); + // loginContext.login(); + + Repository repository = getRepository(); + Session session = repository.login(); + log.debug(session.getUserID()); + } + + @Override + protected Repository createRepository() throws Exception { + URL url = getClass().getResource("test_jaas.config"); + System.setProperty("java.security.auth.login.config", url.toString()); + return super.createRepository(); + } + + @Override + protected void clearRepository(Repository repository) throws Exception { + System.setProperty("java.security.auth.login.config", ""); + } + + @Override + protected String getRepositoryConfigResource() { + return "/org/argeo/security/jackrabbit/repository-memory-test.xml"; + } + +} diff --git a/org.argeo.security.jackrabbit/ext/test/org/argeo/security/jackrabbit/repository-memory-test.xml b/org.argeo.security.jackrabbit/ext/test/org/argeo/security/jackrabbit/repository-memory-test.xml new file mode 100644 index 000000000..e28555574 --- /dev/null +++ b/org.argeo.security.jackrabbit/ext/test/org/argeo/security/jackrabbit/repository-memory-test.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.jackrabbit/ext/test/org/argeo/security/jackrabbit/test_jaas.config b/org.argeo.security.jackrabbit/ext/test/org/argeo/security/jackrabbit/test_jaas.config new file mode 100644 index 000000000..3b4ee81a3 --- /dev/null +++ b/org.argeo.security.jackrabbit/ext/test/org/argeo/security/jackrabbit/test_jaas.config @@ -0,0 +1,3 @@ +Jackrabbit { + org.argeo.security.jackrabbit.SystemJackrabbitLoginModule requisite; +}; diff --git a/org.argeo.security.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java b/org.argeo.security.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java index c4f95458b..0d9d980e0 100644 --- a/org.argeo.security.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java +++ b/org.argeo.security.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java @@ -21,6 +21,7 @@ import java.util.Set; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; import org.apache.jackrabbit.api.security.user.UserManager; import org.apache.jackrabbit.core.DefaultSecurityManager; @@ -28,8 +29,6 @@ import org.apache.jackrabbit.core.security.AMContext; import org.apache.jackrabbit.core.security.AccessManager; import org.apache.jackrabbit.core.security.SecurityConstants; import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; /** Integrates Spring Security and Jackrabbit Security users and roles. */ public class ArgeoSecurityManager extends DefaultSecurityManager { @@ -57,12 +56,20 @@ public class ArgeoSecurityManager extends DefaultSecurityManager { @Override public String getUserID(Subject subject, String workspaceName) throws RepositoryException { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); - if (authentication != null) - return authentication.getName(); - else + Set userPrincipal = subject + .getPrincipals(X500Principal.class); + if (userPrincipal.isEmpty()) return super.getUserID(subject, workspaceName); + if (userPrincipal.size() > 1) + throw new RuntimeException("Multiple user principals " + + userPrincipal); + return userPrincipal.iterator().next().getName(); + // Authentication authentication = SecurityContextHolder.getContext() + // .getAuthentication(); + // if (authentication != null) + // return authentication.getName(); + // else + // return super.getUserID(subject, workspaceName); } @Override diff --git a/org.argeo.security.jackrabbit/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java b/org.argeo.security.jackrabbit/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java new file mode 100644 index 000000000..466402d4e --- /dev/null +++ b/org.argeo.security.jackrabbit/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java @@ -0,0 +1,72 @@ +package org.argeo.security.jackrabbit; + +import java.security.Principal; +import java.util.Map; +import java.util.Set; + +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.login.LoginException; +import javax.security.auth.spi.LoginModule; + +import org.apache.jackrabbit.core.security.AnonymousPrincipal; +import org.apache.jackrabbit.core.security.principal.AdminPrincipal; + +public class SystemJackrabbitLoginModule implements LoginModule { + + private Subject subject; + + @Override + public void initialize(Subject subject, CallbackHandler callbackHandler, + Map sharedState, Map options) { + this.subject = subject; + } + + @Override + public boolean login() throws LoginException { + return true; + } + + @Override + public boolean commit() throws LoginException { + Set principals = subject.getPrincipals(); + if (principals.isEmpty()) {// system + subject.getPrincipals().add(new AdminPrincipal("admin")); + return true; + } + boolean isAdmin = false; + boolean isAnonymous = false; + // FIXME make it more generic + for (Principal principal : principals) { + if (principal.getName().equalsIgnoreCase( + "cn=admin,ou=system,ou=node")) + isAdmin = true; + else if (principal.getName().equalsIgnoreCase( + "cn=anonymous,ou=system,ou=node")) + isAnonymous = true; + } + + if (isAnonymous && isAdmin) + throw new LoginException("Cannot be admin and anonymous"); + + // Add special Jackrabbit roles + if (isAdmin) + principals.add(new AdminPrincipal("admin")); + if (isAnonymous)// anonymous + principals.add(new AnonymousPrincipal()); + return true; + } + + @Override + public boolean abort() throws LoginException { + return true; + } + + @Override + public boolean logout() throws LoginException { + subject.getPrincipals().removeAll( + subject.getPrincipals(AdminPrincipal.class)); + return true; + } + +} diff --git a/org.argeo.security.ui.rap/plugin.xml b/org.argeo.security.ui.rap/plugin.xml index 84df522b0..68d88f240 100644 --- a/org.argeo.security.ui.rap/plugin.xml +++ b/org.argeo.security.ui.rap/plugin.xml @@ -122,7 +122,7 @@ - + @@ -135,7 +135,7 @@ - + diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java index 561a52079..fb885377f 100644 --- a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java +++ b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java @@ -22,6 +22,7 @@ import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.CredentialNotFoundException; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; +import javax.security.auth.x500.X500Principal; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -37,8 +38,6 @@ import org.eclipse.rap.rwt.application.EntryPoint; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; /** * RAP entry point with login capabilities. Once the user has been @@ -96,10 +95,10 @@ public class SecureEntryPoint implements EntryPoint { throw new ArgeoException("Cannot initialize login context", e1); } - tryLogin: while (subject.getPrincipals(Authentication.class).size() == 0) { + tryLogin: while (subject.getPrincipals(X500Principal.class).size() == 0) { try { loginContext.login(); - if (subject.getPrincipals(Authentication.class).size() == 0) + if (subject.getPrincipals(X500Principal.class).size() == 0) throw new ArgeoException("Login succeeded but no auth");// fatal // add security context to session @@ -131,7 +130,7 @@ public class SecureEntryPoint implements EntryPoint { } } - final String username = subject.getPrincipals(Authentication.class) + final String username = subject.getPrincipals(X500Principal.class) .iterator().next().getName(); // Logout callback when the display is disposed display.disposeExec(new Runnable() { @@ -218,7 +217,7 @@ public class SecureEntryPoint implements EntryPoint { private void fullLogout(LoginContext loginContext, String username) { try { loginContext.logout(); - SecurityContextHolder.clearContext(); + // SecurityContextHolder.clearContext(); // HttpServletRequest httpRequest = RWT.getRequest(); // HttpSession httpSession = httpRequest.getSession(); diff --git a/org.argeo.security.ui/plugin.xml b/org.argeo.security.ui/plugin.xml index a1e1e9bdf..6978b3bd6 100644 --- a/org.argeo.security.ui/plugin.xml +++ b/org.argeo.security.ui/plugin.xml @@ -59,7 +59,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -83,7 +83,7 @@ - + @@ -95,7 +95,7 @@ - + @@ -108,7 +108,7 @@ - + diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/internal/CurrentUser.java b/org.argeo.security.ui/src/org/argeo/security/ui/internal/CurrentUser.java index b7287f66c..f5a242d3a 100644 --- a/org.argeo.security.ui/src/org/argeo/security/ui/internal/CurrentUser.java +++ b/org.argeo.security.ui/src/org/argeo/security/ui/internal/CurrentUser.java @@ -15,44 +15,62 @@ */ package org.argeo.security.ui.internal; +import java.security.AccessController; +import java.security.Principal; +import java.security.acl.Group; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; + +import org.argeo.ArgeoException; /** * Retrieves information about the current user. Not an API, can change without * notice. */ public class CurrentUser { - // public final static String getUsername() { - // Subject subject = getSubject(); - // if (subject == null) - // return null; - // Principal principal = subject.getPrincipals().iterator().next(); - // return principal.getName(); - // - // } - public final static String getUsername() { - return getAuthentication().getName(); + Subject subject = getSubject(); + if (subject == null) + return null; + Principal principal = subject.getPrincipals(X500Principal.class) + .iterator().next(); + return principal.getName(); + } public final static Set roles() { Set roles = Collections.synchronizedSet(new HashSet()); - Authentication authentication = getAuthentication(); - for (GrantedAuthority ga : authentication.getAuthorities()) { - roles.add(ga.getAuthority()); + // roles.add("ROLE_USER"); + Subject subject = getSubject(); + X500Principal userPrincipal = subject + .getPrincipals(X500Principal.class).iterator().next(); + roles.add(userPrincipal.getName()); + for (Principal group : subject.getPrincipals(Group.class)) { + roles.add(group.getName()); } - return Collections.unmodifiableSet(roles); + return roles; } - public final static Authentication getAuthentication() { - return SecurityContextHolder.getContext().getAuthentication(); - } + // public final static String getUsername() { + // return getAuthentication().getName(); + // } + + // public final static Set roles() { + // Set roles = Collections.synchronizedSet(new HashSet()); + // Authentication authentication = getAuthentication(); + // for (GrantedAuthority ga : authentication.getAuthorities()) { + // roles.add(ga.getAuthority()); + // } + // return Collections.unmodifiableSet(roles); + // } + // + // public final static Authentication getAuthentication() { + // return SecurityContextHolder.getContext().getAuthentication(); + // } // public final static Authentication getAuthentication() { // Set authens = getSubject().getPrincipals( @@ -65,10 +83,10 @@ public class CurrentUser { // throw new ArgeoException("No authentication found"); // } - // public final static Subject getSubject() { - // Subject subject = Subject.getSubject(AccessController.getContext()); - // if (subject == null) - // throw new ArgeoException("Not authenticated."); - // return subject; - // } + public final static Subject getSubject() { + Subject subject = Subject.getSubject(AccessController.getContext()); + if (subject == null) + throw new ArgeoException("Not authenticated."); + return subject; + } } diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/views/UserProfile.java b/org.argeo.security.ui/src/org/argeo/security/ui/views/UserProfile.java index 590fb35d6..dd7f6cdd2 100644 --- a/org.argeo.security.ui/src/org/argeo/security/ui/views/UserProfile.java +++ b/org.argeo.security.ui/src/org/argeo/security/ui/views/UserProfile.java @@ -42,9 +42,9 @@ public class UserProfile extends ViewPart { public void createPartControl(Composite parent) { parent.setLayout(new GridLayout(2, false)); - Authentication authentication = CurrentUser.getAuthentication(); - EclipseUiUtils.createGridLL(parent, "Name", authentication - .getPrincipal().toString()); +// Authentication authentication = CurrentUser.getAuthentication(); +// EclipseUiUtils.createGridLL(parent, "Name", authentication +// .getPrincipal().toString()); EclipseUiUtils.createGridLL(parent, "User ID", CurrentUser.getUsername()); diff --git a/org.argeo.server.jcr/build.properties b/org.argeo.server.jcr/build.properties index f132db9f9..943d48efe 100644 --- a/org.argeo.server.jcr/build.properties +++ b/org.argeo.server.jcr/build.properties @@ -20,6 +20,5 @@ additional.bundles = org.junit,\ org.apache.lucene,\ org.apache.tika.core,\ org.apache.tika.parsers,\ - org.argeo.security.jackrabbit,\ org.apache.commons.dbcp,\ org.apache.commons.pool diff --git a/org.argeo.server.jcr/src/org/argeo/jackrabbit/unit/AbstractJackrabbitTestCase.java b/org.argeo.server.jcr/src/org/argeo/jackrabbit/unit/AbstractJackrabbitTestCase.java index f1e552308..d3f35b756 100644 --- a/org.argeo.server.jcr/src/org/argeo/jackrabbit/unit/AbstractJackrabbitTestCase.java +++ b/org.argeo.server.jcr/src/org/argeo/jackrabbit/unit/AbstractJackrabbitTestCase.java @@ -37,12 +37,16 @@ public abstract class AbstractJackrabbitTestCase extends AbstractJcrTestCase { // getHomeDir()); RepositoryConfig repositoryConfig = RepositoryConfig.create( AbstractJackrabbitTestCase.class - .getResourceAsStream("repository-memory.xml"), + .getResourceAsStream(getRepositoryConfigResource()), getHomeDir().getAbsolutePath()); RepositoryImpl repositoryImpl = RepositoryImpl.create(repositoryConfig); return repositoryImpl; } + protected String getRepositoryConfigResource() { + return "repository-memory.xml"; + } + @Override protected void clearRepository(Repository repository) throws Exception { RepositoryImpl repositoryImpl = (RepositoryImpl) repository;