]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
Close release cycle
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / security / jackrabbit / ArgeoSecurityManager.java
1 package org.argeo.security.jackrabbit;
2
3 import java.security.Principal;
4 import java.util.HashSet;
5 import java.util.Properties;
6 import java.util.Set;
7
8 import javax.jcr.Credentials;
9 import javax.jcr.Repository;
10 import javax.jcr.RepositoryException;
11 import javax.jcr.Session;
12 import javax.security.auth.Subject;
13 import javax.security.auth.callback.CallbackHandler;
14 import javax.security.auth.x500.X500Principal;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.apache.jackrabbit.api.security.user.UserManager;
19 import org.apache.jackrabbit.core.DefaultSecurityManager;
20 import org.apache.jackrabbit.core.security.AMContext;
21 import org.apache.jackrabbit.core.security.AccessManager;
22 import org.apache.jackrabbit.core.security.SecurityConstants;
23 import org.apache.jackrabbit.core.security.SystemPrincipal;
24 import org.apache.jackrabbit.core.security.authentication.AuthContext;
25 import org.apache.jackrabbit.core.security.authentication.CallbackHandlerImpl;
26 import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
27 import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
28 import org.apache.jackrabbit.core.security.principal.PrincipalProvider;
29 import org.argeo.api.NodeConstants;
30 import org.argeo.api.security.AnonymousPrincipal;
31 import org.argeo.api.security.DataAdminPrincipal;
32 import org.argeo.cms.auth.CmsSession;
33 import org.osgi.framework.BundleContext;
34 import org.osgi.framework.FrameworkUtil;
35
36 /** Customises Jackrabbit security. */
37 public class ArgeoSecurityManager extends DefaultSecurityManager {
38 private final static Log log = LogFactory.getLog(ArgeoSecurityManager.class);
39
40 private BundleContext cmsBundleContext = null;
41
42 public ArgeoSecurityManager() {
43 if (FrameworkUtil.getBundle(CmsSession.class) != null) {
44 cmsBundleContext = FrameworkUtil.getBundle(CmsSession.class).getBundleContext();
45 }
46 }
47
48 public AuthContext getAuthContext(Credentials creds, Subject subject, String workspaceName)
49 throws RepositoryException {
50 checkInitialized();
51
52 CallbackHandler cbHandler = new CallbackHandlerImpl(creds, getSystemSession(), getPrincipalProviderRegistry(),
53 adminId, anonymousId);
54 String appName = "Jackrabbit";
55 return new ArgeoAuthContext(appName, subject, cbHandler);
56 }
57
58 @Override
59 public AccessManager getAccessManager(Session session, AMContext amContext) throws RepositoryException {
60 synchronized (getSystemSession()) {
61 return super.getAccessManager(session, amContext);
62 }
63 }
64
65 @Override
66 public UserManager getUserManager(Session session) throws RepositoryException {
67 synchronized (getSystemSession()) {
68 return super.getUserManager(session);
69 }
70 }
71
72 @Override
73 protected PrincipalProvider createDefaultPrincipalProvider(Properties[] moduleConfig) throws RepositoryException {
74 return super.createDefaultPrincipalProvider(moduleConfig);
75 }
76
77 /** Called once when the session is created */
78 @Override
79 public String getUserID(Subject subject, String workspaceName) throws RepositoryException {
80 boolean isAnonymous = !subject.getPrincipals(AnonymousPrincipal.class).isEmpty();
81 boolean isDataAdmin = !subject.getPrincipals(DataAdminPrincipal.class).isEmpty();
82 boolean isJackrabbitSystem = !subject.getPrincipals(SystemPrincipal.class).isEmpty();
83 Set<X500Principal> userPrincipal = subject.getPrincipals(X500Principal.class);
84 boolean isRegularUser = !userPrincipal.isEmpty();
85 CmsSession cmsSession = null;
86 if (cmsBundleContext != null) {
87 cmsSession = CmsSession.getCmsSession(cmsBundleContext, subject);
88 if (log.isTraceEnabled())
89 log.trace("Opening JCR session for CMS session " + cmsSession);
90 }
91
92 if (isAnonymous) {
93 if (isDataAdmin || isJackrabbitSystem || isRegularUser)
94 throw new IllegalStateException("Inconsistent " + subject);
95 else
96 return NodeConstants.ROLE_ANONYMOUS;
97 } else if (isRegularUser) {// must be before DataAdmin
98 if (isAnonymous || isJackrabbitSystem)
99 throw new IllegalStateException("Inconsistent " + subject);
100 else {
101 if (userPrincipal.size() > 1) {
102 StringBuilder buf = new StringBuilder();
103 for (X500Principal principal : userPrincipal)
104 buf.append(' ').append('\"').append(principal).append('\"');
105 throw new RuntimeException("Multiple user principals:" + buf);
106 }
107 return userPrincipal.iterator().next().getName();
108 }
109 } else if (isDataAdmin) {
110 if (isAnonymous || isJackrabbitSystem || isRegularUser)
111 throw new IllegalStateException("Inconsistent " + subject);
112 else {
113 assert !subject.getPrincipals(AdminPrincipal.class).isEmpty();
114 return NodeConstants.ROLE_DATA_ADMIN;
115 }
116 } else if (isJackrabbitSystem) {
117 if (isAnonymous || isDataAdmin || isRegularUser)
118 throw new IllegalStateException("Inconsistent " + subject);
119 else
120 return super.getUserID(subject, workspaceName);
121 } else {
122 throw new IllegalStateException("Unrecognized subject type: " + subject);
123 }
124 }
125
126 @Override
127 protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() {
128 WorkspaceAccessManager wam = super.createDefaultWorkspaceAccessManager();
129 ArgeoWorkspaceAccessManagerImpl workspaceAccessManager = new ArgeoWorkspaceAccessManagerImpl(wam);
130 if (log.isTraceEnabled())
131 log.trace("Created workspace access manager");
132 return workspaceAccessManager;
133 }
134
135 private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants, WorkspaceAccessManager {
136 private final WorkspaceAccessManager wam;
137
138 public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) {
139 super();
140 this.wam = wam;
141 }
142
143 public void init(Session systemSession) throws RepositoryException {
144 wam.init(systemSession);
145 Repository repository = systemSession.getRepository();
146 if (log.isTraceEnabled())
147 log.trace("Initialised workspace access manager on repository " + repository
148 + ", systemSession workspace: " + systemSession.getWorkspace().getName());
149 }
150
151 public void close() throws RepositoryException {
152 }
153
154 public boolean grants(Set<Principal> principals, String workspaceName) throws RepositoryException {
155 // TODO: implements finer access to workspaces
156 if (log.isTraceEnabled())
157 log.trace("Grants " + new HashSet<>(principals) + " access to workspace '" + workspaceName + "'");
158 return true;
159 // return wam.grants(principals, workspaceName);
160 }
161 }
162
163 }