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