]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
Make log less verbose
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.jackrabbit / src / main / java / org / argeo / security / jackrabbit / ArgeoSecurityManager.java
1 package org.argeo.security.jackrabbit;
2
3 import java.security.Principal;
4 import java.util.ArrayList;
5 import java.util.HashMap;
6 import java.util.Iterator;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Set;
10
11 import javax.jcr.Node;
12 import javax.jcr.PropertyType;
13 import javax.jcr.RepositoryException;
14 import javax.jcr.Session;
15 import javax.jcr.Value;
16 import javax.jcr.ValueFactory;
17 import javax.jcr.security.Privilege;
18 import javax.security.auth.Subject;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
23 import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
24 import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
25 import org.apache.jackrabbit.api.security.user.Group;
26 import org.apache.jackrabbit.api.security.user.User;
27 import org.apache.jackrabbit.api.security.user.UserManager;
28 import org.apache.jackrabbit.core.DefaultSecurityManager;
29 import org.apache.jackrabbit.core.security.SecurityConstants;
30 import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
31 import org.argeo.ArgeoException;
32 import org.argeo.jcr.JcrUtils;
33 import org.springframework.security.Authentication;
34 import org.springframework.security.GrantedAuthority;
35
36 /** Intermediary class in order to have a consistent naming in config files. */
37 public class ArgeoSecurityManager extends DefaultSecurityManager {
38 private Log log = LogFactory.getLog(ArgeoSecurityManager.class);
39
40 /**
41 * Since this is called once when the session is created, we take the
42 * opportunity to make sure that Jackrabbit users and groups reflect Spring
43 * Security name and authorities.
44 */
45 @Override
46 public String getUserID(Subject subject, String workspaceName)
47 throws RepositoryException {
48 long begin = System.currentTimeMillis();
49
50 if (log.isTraceEnabled())
51 log.trace(subject);
52 // skip Jackrabbit system user
53 if (!subject.getPrincipals(ArgeoSystemPrincipal.class).isEmpty())
54 return super.getUserID(subject, workspaceName);
55
56 Authentication authen;
57 Set<Authentication> authens = subject
58 .getPrincipals(Authentication.class);
59 if (authens.size() == 0)
60 throw new ArgeoException("No Spring authentication found in "
61 + subject);
62 else
63 authen = authens.iterator().next();
64
65 UserManager systemUm = getSystemUserManager(workspaceName);
66
67 String userId = authen.getName();
68 User user = (User) systemUm.getAuthorizable(userId);
69 if (user == null) {
70 user = systemUm.createUser(userId, authen.getCredentials()
71 .toString(), authen, null);
72 setSecurityHomeAuthorizations(user);
73 log.info(userId + " added as " + user);
74 }
75
76 // process groups
77 List<String> userGroupIds = new ArrayList<String>();
78 for (GrantedAuthority ga : authen.getAuthorities()) {
79 Group group = (Group) systemUm.getAuthorizable(ga.getAuthority());
80 if (group == null) {
81 group = systemUm.createGroup(ga.getAuthority());
82 log.info(ga.getAuthority() + " added as " + group);
83 }
84 if (!group.isMember(user))
85 group.addMember(user);
86 userGroupIds.add(ga.getAuthority());
87 }
88
89 // check if user has not been removed from some groups
90 for (Iterator<Group> it = user.declaredMemberOf(); it.hasNext();) {
91 Group group = it.next();
92 if (!userGroupIds.contains(group.getID()))
93 group.removeMember(user);
94 }
95
96 if (log.isDebugEnabled())
97 log.debug("Spring and Jackrabbit Security synchronized for user "
98 + userId + " in " + (System.currentTimeMillis() - begin)
99 + " ms");
100 return userId;
101 }
102
103 protected synchronized void setSecurityHomeAuthorizations(User user) {
104 // give read privileges on user home
105 String userId = "<not yet set>";
106 try {
107 userId = user.getID();
108 Node userHome = JcrUtils.getUserHome(getSystemSession(), userId);
109 if (userHome == null)
110 throw new ArgeoException("No security home available for user "
111 + userId);
112
113 String path = userHome.getPath();
114 Principal principal = user.getPrincipal();
115
116 JackrabbitAccessControlManager acm = (JackrabbitAccessControlManager) getSystemSession()
117 .getAccessControlManager();
118 JackrabbitAccessControlPolicy[] ps = acm
119 .getApplicablePolicies(principal);
120 if (ps.length == 0) {
121 // log.warn("No ACL found for " + user);
122 return;
123 }
124
125 JackrabbitAccessControlList list = (JackrabbitAccessControlList) ps[0];
126
127 // add entry
128 Privilege[] privileges = new Privilege[] { acm
129 .privilegeFromName(Privilege.JCR_READ) };
130 Map<String, Value> restrictions = new HashMap<String, Value>();
131 ValueFactory vf = getSystemSession().getValueFactory();
132 restrictions.put("rep:nodePath",
133 vf.createValue(path, PropertyType.PATH));
134 restrictions.put("rep:glob", vf.createValue("*"));
135 list.addEntry(principal, privileges, true /* allow or deny */,
136 restrictions);
137 } catch (Exception e) {
138 e.printStackTrace();
139 throw new ArgeoException(
140 "Cannot set authorization on security home for " + userId
141 + ": " + e.getMessage());
142 }
143
144 }
145
146 @Override
147 protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() {
148 WorkspaceAccessManager wam = super
149 .createDefaultWorkspaceAccessManager();
150 return new ArgeoWorkspaceAccessManagerImpl(wam);
151 }
152
153 private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants,
154 WorkspaceAccessManager {
155 private final WorkspaceAccessManager wam;
156
157 // private String defaultWorkspace;
158
159 public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) {
160 super();
161 this.wam = wam;
162 }
163
164 public void init(Session systemSession) throws RepositoryException {
165 wam.init(systemSession);
166 // defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
167 // .getDefaultWorkspaceName();
168 }
169
170 public void close() throws RepositoryException {
171 }
172
173 public boolean grants(Set<Principal> principals, String workspaceName)
174 throws RepositoryException {
175 // everybody has access to all workspaces
176 // TODO: implements finer access to workspaces
177 return true;
178
179 // anonymous has access to the default workspace (required for
180 // remoting which does a default login when initializing the
181 // repository)
182 // Boolean anonymous = false;
183 // for (Principal principal : principals)
184 // if (principal instanceof AnonymousPrincipal)
185 // anonymous = true;
186 //
187 // if (anonymous && workspaceName.equals(defaultWorkspace))
188 // return true;
189 // else
190 // return wam.grants(principals, workspaceName);
191 }
192 }
193
194 }