1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.mcr.acl.accesskey;
20
21 import java.util.ArrayList;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Optional;
25 import java.util.Set;
26 import java.util.concurrent.TimeUnit;
27 import java.util.stream.Collectors;
28
29 import org.mycore.access.MCRAccessCacheHelper;
30 import org.mycore.access.MCRAccessManager;
31 import org.mycore.common.MCRException;
32 import org.mycore.common.MCRSession;
33 import org.mycore.common.MCRSessionMgr;
34 import org.mycore.common.MCRUserInformation;
35 import org.mycore.common.config.MCRConfiguration2;
36 import org.mycore.datamodel.metadata.MCRMetadataManager;
37 import org.mycore.datamodel.metadata.MCRObjectID;
38 import org.mycore.mcr.acl.accesskey.model.MCRAccessKey;
39 import org.mycore.mcr.acl.accesskey.exception.MCRAccessKeyException;
40 import org.mycore.mcr.acl.accesskey.exception.MCRAccessKeyNotFoundException;
41 import org.mycore.user2.MCRUser;
42 import org.mycore.user2.MCRUserAttribute;
43 import org.mycore.user2.MCRUserManager;
44
45
46
47
48 public class MCRAccessKeyUtils {
49
50
51
52 public static final String ACCESS_KEY_PREFIX = "acckey_";
53
54 private static final String ACCESS_KEY_STRATEGY_PROP_PREFX = "MCR.ACL.AccessKey.Strategy";
55
56 private static final String ALLOWED_OBJECT_TYPES_PROP = ACCESS_KEY_STRATEGY_PROP_PREFX + ".AllowedObjectTypes";
57
58 private static final String ALLOWED_SESSION_PERMISSION_TYPES_PROP = ACCESS_KEY_STRATEGY_PROP_PREFX
59 + ".AllowedSessionPermissionTypes";
60
61 private static Set<String> allowedObjectTypes = loadAllowedObjectTypes();
62
63 private static Set<String> allowedSessionPermissionTypes = loadAllowedSessionPermissionTypes();
64
65 private static Set<String> parseListStringToSet(final Optional<String> listString) {
66 return listString.stream()
67 .flatMap(MCRConfiguration2::splitValue)
68 .collect(Collectors.toSet());
69 }
70
71 private static Set<String> loadAllowedObjectTypes() {
72 MCRConfiguration2.addPropertyChangeEventLister(ALLOWED_OBJECT_TYPES_PROP::equals, (p1, p2, p3) -> {
73 allowedObjectTypes = parseListStringToSet(p3);
74 });
75 return parseListStringToSet(MCRConfiguration2.getString(ALLOWED_OBJECT_TYPES_PROP));
76 }
77
78 private static Set<String> loadAllowedSessionPermissionTypes() {
79 MCRConfiguration2.addPropertyChangeEventLister(ALLOWED_SESSION_PERMISSION_TYPES_PROP::equals, (p1, p2, p3) -> {
80 allowedSessionPermissionTypes = parseListStringToSet(p3);
81 });
82 return parseListStringToSet(MCRConfiguration2.getString(ALLOWED_SESSION_PERMISSION_TYPES_PROP));
83 }
84
85
86
87
88
89
90
91
92
93 public static synchronized void addAccessKeySecretForObject(final MCRSession session, final MCRObjectID objectId,
94 final String value) throws MCRException {
95 if (!isAccessKeyForSessionAllowed()) {
96 throw new MCRAccessKeyException("Access keys is not allowed.");
97 }
98 if (isAccessKeyForObjectTypeAllowed(objectId.getTypeId())) {
99 final String secret = MCRAccessKeyManager.hashSecret(value, objectId);
100 final MCRAccessKey accessKey = MCRAccessKeyManager.getAccessKeyWithSecret(objectId, secret);
101 if (accessKey == null) {
102 throw new MCRAccessKeyNotFoundException("Access key is invalid.");
103 } else if (isAccessKeyForSessionAllowed(accessKey.getType())) {
104 session.put(getAttributeName(objectId), secret);
105 MCRAccessManager.invalidPermissionCacheByID(objectId.toString());
106 } else {
107 throw new MCRAccessKeyException("Access key is not allowed.");
108 }
109 } else {
110 throw new MCRAccessKeyException("Access key is not allowed.");
111 }
112 }
113
114
115
116
117
118
119
120
121
122
123 public static synchronized void addAccessKeySecret(final MCRSession session, final MCRObjectID objectId,
124 final String value) throws MCRException {
125 if (!isAccessKeyForSessionAllowed()) {
126 throw new MCRAccessKeyException("Access keys is not allowed.");
127 }
128 if ("derivate".equals(objectId.getTypeId())) {
129 addAccessKeySecretForObject(session, objectId, value);
130 } else {
131 boolean success = false;
132 try {
133 addAccessKeySecretForObject(session, objectId, value);
134 MCRAccessCacheHelper.clearPermissionCache(objectId.toString());
135 success = true;
136 } catch (MCRAccessKeyException e) {
137
138 }
139 final List<MCRObjectID> derivateIds = MCRMetadataManager.getDerivateIds(objectId, 0, TimeUnit.SECONDS);
140 for (final MCRObjectID derivateId : derivateIds) {
141 try {
142 addAccessKeySecretForObject(session, derivateId, value);
143 success = true;
144 } catch (MCRAccessKeyException e) {
145
146 }
147 }
148 if (!success) {
149 throw new MCRAccessKeyException("Access key is invalid or is not allowed.");
150 }
151 }
152 }
153
154
155
156
157
158
159
160
161
162 public static synchronized void addAccessKeySecretForObject(final MCRUser user, final MCRObjectID objectId,
163 final String value) throws MCRException {
164 if (isAccessKeyForObjectTypeAllowed(objectId.getTypeId())) {
165 final String secret = MCRAccessKeyManager.hashSecret(value, objectId);
166 final MCRAccessKey accessKey = MCRAccessKeyManager.getAccessKeyWithSecret(objectId, secret);
167 if (accessKey == null) {
168 throw new MCRAccessKeyNotFoundException("Access key is invalid.");
169 } else {
170 user.setUserAttribute(getAttributeName(objectId), secret);
171 MCRUserManager.updateUser(user);
172 MCRAccessManager.invalidPermissionCacheByID(objectId.toString());
173 }
174 } else {
175 throw new MCRAccessKeyException("Access key is not allowed.");
176 }
177 }
178
179
180
181
182
183
184
185
186
187
188 public static synchronized void addAccessKeySecret(final MCRUser user, final MCRObjectID objectId,
189 final String value) throws MCRException {
190 if ("derivate".equals(objectId.getTypeId())) {
191 addAccessKeySecretForObject(user, objectId, value);
192 } else {
193 boolean success = false;
194 try {
195 addAccessKeySecretForObject(user, objectId, value);
196 MCRAccessCacheHelper.clearPermissionCache(objectId.toString());
197 success = true;
198 } catch (MCRAccessKeyException e) {
199
200 }
201 final List<MCRObjectID> derivateIds = MCRMetadataManager.getDerivateIds(objectId, 0, TimeUnit.SECONDS);
202 for (final MCRObjectID derivateId : derivateIds) {
203 try {
204 addAccessKeySecretForObject(user, derivateId, value);
205 success = true;
206 } catch (MCRAccessKeyException e) {
207
208 }
209 }
210 if (!success) {
211 throw new MCRAccessKeyException("Access key is invalid or is not allowed.");
212 }
213 }
214 }
215
216
217
218
219
220
221
222
223 public static synchronized void addAccessKeySecretToCurrentSession(final MCRObjectID objectId, final String value)
224 throws MCRException {
225 addAccessKeySecret(MCRSessionMgr.getCurrentSession(), objectId, value);
226 }
227
228
229
230
231
232
233
234
235 public static synchronized void addAccessKeySecretToCurrentUser(final MCRObjectID objectId, final String value)
236 throws MCRException {
237 addAccessKeySecret(MCRUserManager.getCurrentUser(), objectId, value);
238 }
239
240
241
242
243
244
245
246
247 private static List<MCRUser> listUsersWithAccessKey(final int offset, final int limit) {
248 return MCRUserManager.listUsers(null, null, null, null, ACCESS_KEY_PREFIX + "*", offset, limit);
249 }
250
251
252
253
254 public static void cleanUpUserAttributes() {
255 final Set<MCRUserAttribute> validAttributes = new HashSet<>();
256 final Set<MCRUserAttribute> deadAttributes = new HashSet<>();
257 int offset = 0;
258 final int limit = 1024;
259 List<MCRUser> users = new ArrayList<>();
260 do {
261 users = listUsersWithAccessKey(offset, limit);
262 for (final MCRUser user : users) {
263 final List<MCRUserAttribute> attributes = user.getAttributes()
264 .stream()
265 .filter(attribute -> attribute.getName().startsWith(MCRAccessKeyUtils.ACCESS_KEY_PREFIX))
266 .filter(attribute -> !validAttributes.contains(attribute))
267 .collect(Collectors.toList());
268 for (MCRUserAttribute attribute : attributes) {
269 final String attributeName = attribute.getName();
270 final MCRObjectID objectId = MCRObjectID.getInstance(attributeName.substring(
271 attributeName.indexOf("_") + 1));
272 if (deadAttributes.contains(attribute)) {
273 MCRAccessKeyUtils.removeAccessKeySecret(user, objectId);
274 } else {
275 if (MCRAccessKeyManager.getAccessKeyWithSecret(objectId, attribute.getValue()) != null) {
276 validAttributes.add(attribute);
277 } else {
278 MCRAccessKeyUtils.removeAccessKeySecret(user, objectId);
279 deadAttributes.add(attribute);
280 }
281 }
282 }
283 }
284 offset += limit;
285 } while (users.size() == limit);
286 }
287
288
289
290
291
292
293
294
295 public static synchronized String getAccessKeySecret(final MCRSession session, final MCRObjectID objectId) {
296 final Object secret = session.get(getAttributeName(objectId));
297 if (secret != null) {
298 return (String) secret;
299 }
300 return null;
301 }
302
303
304
305
306
307
308
309
310 public static synchronized String getAccessKeySecret(final MCRUserInformation userInformation,
311 final MCRObjectID objectId) {
312 return userInformation.getUserAttribute(getAttributeName(objectId));
313 }
314
315
316
317
318
319
320
321 public static synchronized String getAccessKeySecretFromCurrentSession(final MCRObjectID objectId) {
322 return getAccessKeySecret(MCRSessionMgr.getCurrentSession(), objectId);
323 }
324
325
326
327
328
329
330
331 public static synchronized String getAccessKeySecretFromCurrentUser(final MCRObjectID objectId) {
332 return getAccessKeySecret(MCRSessionMgr.getCurrentSession().getUserInformation(), objectId);
333 }
334
335
336
337
338
339
340
341 private static String getAttributeName(final MCRObjectID objectId) {
342 return ACCESS_KEY_PREFIX + objectId.toString();
343 }
344
345
346
347
348
349
350
351
352 public static MCRAccessKey getLinkedAccessKey(final MCRSession session,
353 final MCRObjectID objectId) {
354 final String secret = getAccessKeySecret(session, objectId);
355 if (secret != null) {
356 return MCRAccessKeyManager.getAccessKeyWithSecret(objectId, secret);
357 }
358 return null;
359 }
360
361
362
363
364
365
366
367
368 public static MCRAccessKey getLinkedAccessKey(final MCRUserInformation userInformation,
369 final MCRObjectID objectId) {
370 final String secret = getAccessKeySecret(userInformation, objectId);
371 if (secret != null) {
372 return MCRAccessKeyManager.getAccessKeyWithSecret(objectId, secret);
373 }
374 return null;
375 }
376
377
378
379
380
381
382
383 public static MCRAccessKey getLinkedAccessKeyFromCurrentSession(final MCRObjectID objectId) {
384 return getLinkedAccessKey(MCRSessionMgr.getCurrentSession(), objectId);
385 }
386
387
388
389
390
391
392
393 public static MCRAccessKey getLinkedAccessKeyFromCurrentUser(final MCRObjectID objectId) {
394 return getLinkedAccessKey(MCRSessionMgr.getCurrentSession().getUserInformation(), objectId);
395 }
396
397
398
399
400
401
402
403 public static synchronized void removeAccessKeySecret(final MCRSession session, final MCRObjectID objectId) {
404 session.deleteObject(getAttributeName(objectId));
405 MCRAccessCacheHelper.clearPermissionCache(objectId.toString());
406 }
407
408
409
410
411
412
413
414 public static synchronized void removeAccessKeySecret(final MCRUser user, final MCRObjectID objectId) {
415 user.getAttributes().removeIf(ua -> ua.getName().equals(getAttributeName(objectId)));
416 MCRUserManager.updateUser(user);
417 MCRAccessCacheHelper.clearPermissionCache(objectId.toString());
418 }
419
420
421
422
423
424
425 public static synchronized void removeAccessKeySecretFromCurrentSession(final MCRObjectID objectId) {
426 removeAccessKeySecret(MCRSessionMgr.getCurrentSession(), objectId);
427 }
428
429
430
431
432
433
434 public static synchronized void removeAccessKeySecretFromCurrentUser(final MCRObjectID objectId) {
435 removeAccessKeySecret(MCRUserManager.getCurrentUser(), objectId);
436 }
437
438 public static boolean isAccessKeyForSessionAllowed() {
439 return !allowedSessionPermissionTypes.isEmpty();
440 }
441
442 public static boolean isAccessKeyForSessionAllowed(final String permission) {
443 return allowedSessionPermissionTypes.contains(permission);
444 }
445
446 public static boolean isAccessKeyForObjectTypeAllowed(final String type) {
447 return allowedObjectTypes.contains(type);
448 }
449
450 public static Set<String> getAllowedSessionPermissionTypes() {
451 return allowedSessionPermissionTypes;
452 }
453 }