]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
Reduce log verbosity
[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 JcrUtils.createUserHomeIfNeeded(getSystemSession(), userId);
73 getSystemSession().save();
74 setSecurityHomeAuthorizations(user);
75 log.info(userId + " added as " + user);
76 }
77
78 // process groups
79 List<String> userGroupIds = new ArrayList<String>();
80 for (GrantedAuthority ga : authen.getAuthorities()) {
81 Group group = (Group) systemUm.getAuthorizable(ga.getAuthority());
82 if (group == null) {
83 group = systemUm.createGroup(ga.getAuthority());
84 log.info(ga.getAuthority() + " added as " + group);
85 }
86 if (!group.isMember(user))
87 group.addMember(user);
88 userGroupIds.add(ga.getAuthority());
89 }
90
91 // check if user has not been removed from some groups
92 for (Iterator<Group> it = user.declaredMemberOf(); it.hasNext();) {
93 Group group = it.next();
94 if (!userGroupIds.contains(group.getID()))
95 group.removeMember(user);
96 }
97
98 if (log.isTraceEnabled())
99 log.trace("Spring and Jackrabbit Security synchronized for user "
100 + userId + " in " + (System.currentTimeMillis() - begin)
101 + " ms");
102 return userId;
103 }
104
105 protected synchronized void setSecurityHomeAuthorizations(User user) {
106 // give read privileges on user security home
107 String userId = "<not yet set>";
108 try {
109 userId = user.getID();
110 Node userHome = JcrUtils.getUserHome(getSystemSession(), userId);
111 if (userHome == null)
112 throw new ArgeoException("No security home available for user "
113 + userId);
114
115 String path = userHome.getPath();
116 Principal principal = user.getPrincipal();
117
118 JackrabbitAccessControlManager acm = (JackrabbitAccessControlManager) getSystemSession()
119 .getAccessControlManager();
120 JackrabbitAccessControlPolicy[] ps = acm
121 .getApplicablePolicies(principal);
122 if (ps.length == 0) {
123 // log.warn("No ACL found for " + user);
124 return;
125 }
126
127 JackrabbitAccessControlList list = (JackrabbitAccessControlList) ps[0];
128
129 // add entry
130 Privilege[] privileges = new Privilege[] { acm
131 .privilegeFromName(Privilege.JCR_READ) };
132 Map<String, Value> restrictions = new HashMap<String, Value>();
133 ValueFactory vf = getSystemSession().getValueFactory();
134 restrictions.put("rep:nodePath",
135 vf.createValue(path, PropertyType.PATH));
136 restrictions.put("rep:glob", vf.createValue("*"));
137 list.addEntry(principal, privileges, true /* allow or deny */,
138 restrictions);
139 } catch (Exception e) {
140 e.printStackTrace();
141 throw new ArgeoException(
142 "Cannot set authorization on security home for " + userId
143 + ": " + e.getMessage());
144 }
145
146 }
147
148 @Override
149 protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() {
150 WorkspaceAccessManager wam = super
151 .createDefaultWorkspaceAccessManager();
152 return new ArgeoWorkspaceAccessManagerImpl(wam);
153 }
154
155 private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants,
156 WorkspaceAccessManager {
157 private final WorkspaceAccessManager wam;
158
159 // private String defaultWorkspace;
160
161 public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) {
162 super();
163 this.wam = wam;
164 }
165
166 public void init(Session systemSession) throws RepositoryException {
167 wam.init(systemSession);
168 // defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
169 // .getDefaultWorkspaceName();
170 }
171
172 public void close() throws RepositoryException {
173 }
174
175 public boolean grants(Set<Principal> principals, String workspaceName)
176 throws RepositoryException {
177 // everybody has access to all workspaces
178 // TODO: implements finer access to workspaces
179 return true;
180
181 // anonymous has access to the default workspace (required for
182 // remoting which does a default login when initializing the
183 // repository)
184 // Boolean anonymous = false;
185 // for (Principal principal : principals)
186 // if (principal instanceof AnonymousPrincipal)
187 // anonymous = true;
188 //
189 // if (anonymous && workspaceName.equals(defaultWorkspace))
190 // return true;
191 // else
192 // return wam.grants(principals, workspaceName);
193 }
194 }
195
196 }