2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
24 package org.collectionspace.services.authorization.importer;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import java.util.ArrayList;
30 import java.util.Date;
31 import java.util.Hashtable;
32 import java.util.List;
33 import java.util.UUID;
34 import javax.xml.bind.JAXBContext;
35 import javax.xml.bind.Marshaller;
36 import org.collectionspace.services.authorization.perms.ActionType;
37 import org.collectionspace.services.authorization.perms.Permission;
38 import org.collectionspace.services.authorization.perms.EffectType;
39 import org.collectionspace.services.authorization.perms.PermissionAction;
40 import org.collectionspace.services.authorization.PermissionActionUtil;
41 import org.collectionspace.services.authorization.PermissionRole;
42 import org.collectionspace.services.authorization.PermissionValue;
43 import org.collectionspace.services.authorization.perms.PermissionsList;
44 import org.collectionspace.services.authorization.PermissionsRolesList;
45 import org.collectionspace.services.client.RoleClient;
46 import org.collectionspace.services.authorization.Role;
47 import org.collectionspace.services.authorization.RoleValue;
48 import org.collectionspace.services.authorization.RolesList;
49 import org.collectionspace.services.authorization.SubjectType;
50 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
51 import org.collectionspace.services.common.service.ServiceBindingType;
52 import org.collectionspace.services.common.tenant.TenantBindingType;
53 import org.collectionspace.services.common.security.SecurityUtils;
56 * AuthorizationGen generates authorizations (permissions and roles)
60 public class AuthorizationGen {
62 final public static String ROLE_PREFIX = "ROLE_";
63 final public static String ROLE_ADMINISTRATOR = "ADMINISTRATOR";
64 final public static String ROLE_TENANT_ADMINISTRATOR = "TENANT_ADMINISTRATOR";
65 final public static String ROLE_TENANT_READER = "TENANT_READER";
66 final public static String ROLE_ADMINISTRATOR_ID = "0";
67 final public static String ADMINISTRATOR_TENANT_ID = "0";
69 // ActionGroup labels/constants
71 final public static String ACTIONGROUP_CRUDL = "CRUDL";
72 final public static String ACTIONGROUP_RL = "RL";
74 // Should the base resource act as a proxy for its sub-resources for AuthZ purposes
76 final public static boolean AUTHZ_IS_ENTITY_PROXY = false;
78 final Logger logger = LoggerFactory.getLogger(AuthorizationGen.class);
79 private List<Permission> adminPermList = new ArrayList<Permission>();
80 private List<PermissionRole> adminPermRoleList = new ArrayList<PermissionRole>();
81 private List<Permission> readerPermList = new ArrayList<Permission>();
82 private List<PermissionRole> readerPermRoleList = new ArrayList<PermissionRole>();
83 private List<Role> adminRoles = new ArrayList<Role>();
84 private List<Role> readerRoles = new ArrayList<Role>();
85 private Role cspaceAdminRole;
86 private Hashtable<String, TenantBindingType> tenantBindings =
87 new Hashtable<String, TenantBindingType>();
89 public void initialize(String tenantRootDirPath) throws Exception {
90 TenantBindingConfigReaderImpl tenantBindingConfigReader =
91 new TenantBindingConfigReaderImpl(tenantRootDirPath);
92 tenantBindingConfigReader.read();
93 tenantBindings = tenantBindingConfigReader.getTenantBindings();
94 cspaceAdminRole = buildCSpaceAdminRole();
96 if (logger.isDebugEnabled()) {
97 logger.debug("initialized with tenant bindings from " + tenantRootDirPath);
102 * createDefaultPermissions creates default admin and reader permissions
103 * for each tenant found in the given tenant binding file
107 public void createDefaultPermissions() {
108 for (String tenantId : tenantBindings.keySet()) {
109 List<Permission> adminPerms = createDefaultAdminPermissions(tenantId, AUTHZ_IS_ENTITY_PROXY);
110 adminPermList.addAll(adminPerms);
112 List<Permission> readerPerms = createDefaultReaderPermissions(tenantId, AUTHZ_IS_ENTITY_PROXY);
113 readerPermList.addAll(readerPerms);
118 * createDefaultAdminPermissions creates default admin permissions for all services
119 * used by the given tenant
123 public List<Permission> createDefaultAdminPermissions(String tenantId, boolean isEntityProxy) {
124 ArrayList<Permission> apcList = new ArrayList<Permission>();
125 TenantBindingType tbinding = tenantBindings.get(tenantId);
126 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
128 //add permissions for the main path
129 String resourceName = sbinding.getName().toLowerCase().trim();
130 if (isEntityProxy == true) {
131 resourceName = SecurityUtils.getResourceEntity(resourceName);
133 Permission perm = buildAdminPermission(tbinding.getId(),
137 //add permissions for alternate paths
138 if (isEntityProxy == false) {
139 List<String> uriPaths = sbinding.getUriPath();
140 for (String uriPath : uriPaths) {
141 perm = buildAdminPermission(tbinding.getId(),
142 uriPath.toLowerCase());
151 private Permission buildAdminPermission(String tenantId, String resourceName) {
152 String id = UUID.randomUUID().toString();
153 Permission perm = new Permission();
155 perm.setDescription("generated admin permission");
156 perm.setCreatedAtItem(new Date());
157 perm.setResourceName(resourceName.toLowerCase().trim());
158 perm.setEffect(EffectType.PERMIT);
159 perm.setTenantId(tenantId);
161 perm.setActionGroup(ACTIONGROUP_CRUDL);
162 ArrayList<PermissionAction> pas = new ArrayList<PermissionAction>();
165 PermissionAction permAction = PermissionActionUtil.create(perm, ActionType.CREATE);
168 permAction = PermissionActionUtil.create(perm, ActionType.READ);
171 permAction = PermissionActionUtil.create(perm, ActionType.UPDATE);
174 permAction = PermissionActionUtil.create(perm, ActionType.DELETE);
177 permAction = PermissionActionUtil.create(perm, ActionType.SEARCH);
184 * createDefaultReaderPermissions creates read only permissions for all services
185 * used by the given tenant
189 public List<Permission> createDefaultReaderPermissions(String tenantId, boolean isEntityProxy) {
190 ArrayList<Permission> apcList = new ArrayList<Permission>();
191 TenantBindingType tbinding = tenantBindings.get(tenantId);
192 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
193 //add permissions for the main path
194 String resourceName = sbinding.getName().toLowerCase().trim();
195 if (isEntityProxy == true) {
196 resourceName = SecurityUtils.getResourceEntity(resourceName);
198 Permission perm = buildReaderPermission(tbinding.getId(),
202 //add permissions for alternate paths
203 if (isEntityProxy == false) {
204 List<String> uriPaths = sbinding.getUriPath();
205 for (String uriPath : uriPaths) {
206 perm = buildReaderPermission(tbinding.getId(),
207 uriPath.toLowerCase());
216 private Permission buildReaderPermission(String tenantId, String resourceName) {
217 String id = UUID.randomUUID().toString();
218 Permission perm = new Permission();
220 perm.setCreatedAtItem(new Date());
221 perm.setDescription("generated readonly permission");
222 perm.setResourceName(resourceName.toLowerCase().trim());
223 perm.setEffect(EffectType.PERMIT);
224 perm.setTenantId(tenantId);
226 perm.setActionGroup(ACTIONGROUP_RL);
227 ArrayList<PermissionAction> pas = new ArrayList<PermissionAction>();
230 PermissionAction permAction = PermissionActionUtil.create(perm, ActionType.READ);
233 permAction = PermissionActionUtil.create(perm, ActionType.SEARCH);
239 public List<Permission> getDefaultPermissions() {
240 List<Permission> allPermList = new ArrayList<Permission>();
241 allPermList.addAll(adminPermList);
242 allPermList.addAll(readerPermList);
246 public List<Permission> getDefaultAdminPermissions() {
247 return adminPermList;
250 public List<Permission> getDefaultReaderPermissions() {
251 return readerPermList;
255 * createDefaultRoles creates default admin and reader roles
256 * for each tenant found in the given tenant binding file
258 public void createDefaultRoles() {
259 for (String tenantId : tenantBindings.keySet()) {
261 Role arole = buildTenantAdminRole(tenantId);
262 adminRoles.add(arole);
264 Role rrole = buildTenantReaderRole(tenantId);
265 readerRoles.add(rrole);
269 private Role buildTenantAdminRole(String tenantId) {
270 return buildTenantRole(tenantId, ROLE_TENANT_ADMINISTRATOR, "admin");
273 private Role buildTenantReaderRole(String tenantId) {
274 return buildTenantRole(tenantId, ROLE_TENANT_READER, "read only");
277 private Role buildTenantRole(String tenantId, String name, String type) {
278 Role role = new Role();
279 role.setCreatedAtItem(new Date());
280 role.setDisplayName(name);
281 role.setRoleName(ROLE_PREFIX +
283 role.getDisplayName());
284 String id = UUID.randomUUID().toString();
286 role.setDescription("generated tenant "+type+" role");
287 role.setTenantId(tenantId);
288 role.setMetadataProtection(RoleClient.IMMUTABLE);
289 role.setPermsProtection(RoleClient.IMMUTABLE);
293 public List<Role> getDefaultRoles() {
294 List<Role> allRoleList = new ArrayList<Role>();
295 allRoleList.addAll(adminRoles);
296 allRoleList.addAll(readerRoles);
300 public void associateDefaultPermissionsRoles() {
301 for (Permission p : adminPermList) {
302 PermissionRole permAdmRole = associatePermissionRoles(p, adminRoles, true);
303 adminPermRoleList.add(permAdmRole);
306 for (Permission p : readerPermList) {
307 PermissionRole permRdrRole = associatePermissionRoles(p, readerRoles, true);
308 readerPermRoleList.add(permRdrRole);
311 //CSpace Administrator has all access
312 List<Role> roles = new ArrayList<Role>();
313 roles.add(cspaceAdminRole);
314 for (Permission p : adminPermList) {
315 PermissionRole permCAdmRole = associatePermissionRoles(p, roles, false);
316 adminPermRoleList.add(permCAdmRole);
320 public List<PermissionRole> associatePermissionsRoles(List<Permission> perms, List<Role> roles, boolean enforceTenancy) {
321 List<PermissionRole> result = null;
323 List<PermissionRole> permRoles = new ArrayList<PermissionRole>();
324 for (Permission perm : perms) {
325 PermissionRole permRole = associatePermissionRoles(perm, roles, enforceTenancy);
326 if (permRole != null) {
327 permRoles.add(permRole);
331 if (permRoles.isEmpty() == false) {
338 private PermissionRole associatePermissionRoles(Permission perm,
339 List<Role> roles, boolean enforceTenancy) {
340 PermissionRole result = null;
342 PermissionRole pr = new PermissionRole();
343 pr.setSubject(SubjectType.ROLE);
344 List<PermissionValue> permValues = new ArrayList<PermissionValue>();
345 pr.setPermission(permValues);
346 PermissionValue permValue = new PermissionValue();
347 permValue.setPermissionId(perm.getCsid());
348 permValue.setResourceName(perm.getResourceName().toLowerCase());
349 permValue.setActionGroup(perm.getActionGroup());
350 permValues.add(permValue);
352 List<RoleValue> roleValues = new ArrayList<RoleValue>();
353 for (Role role : roles) {
354 boolean tenantIdsMatched = true;
355 if (enforceTenancy == true) {
356 tenantIdsMatched = role.getTenantId().equals(perm.getTenantId());
358 if (tenantIdsMatched == true) {
359 RoleValue rv = new RoleValue();
360 // This needs to use the qualified name, not the display name
361 rv.setRoleName(role.getRoleName().toUpperCase());
362 rv.setRoleId(role.getCsid());
365 if (logger.isTraceEnabled() == true) {
366 logger.trace("Role and Permission tenant ID did not match."); //FIXME: REM - Remove this debug statement.
371 // If 'roleValues' is not empty, then associate it with the incoming 'perm' values
372 // otherwise, return null;
374 if (roleValues.isEmpty() == false) {
375 pr.setRole(roleValues);
382 public List<PermissionRole> getDefaultPermissionRoles() {
383 List<PermissionRole> allPermRoleList = new ArrayList<PermissionRole>();
384 allPermRoleList.addAll(adminPermRoleList);
385 allPermRoleList.addAll(readerPermRoleList);
386 return allPermRoleList;
389 public List<PermissionRole> getDefaultAdminPermissionRoles() {
390 return adminPermRoleList;
393 public List<PermissionRole> getDefaultReaderPermissionRoles() {
394 return readerPermRoleList;
397 private Role buildCSpaceAdminRole() {
398 Role role = new Role();
399 role.setDisplayName(ROLE_ADMINISTRATOR);
400 role.setRoleName(ROLE_PREFIX + role.getDisplayName());
401 role.setCsid(ROLE_ADMINISTRATOR_ID);
402 role.setTenantId(ADMINISTRATOR_TENANT_ID);
406 public void exportDefaultRoles(String fileName) {
407 RolesList rList = new RolesList();
408 List<Role> allRoleList = new ArrayList<Role>();
409 allRoleList.addAll(adminRoles);
410 allRoleList.addAll(readerRoles);
411 rList.setRole(allRoleList);
413 // Since it is missing the @XMLRootElement annotation, create a JAXBElement wrapper for the RoleList instance
414 // so we can have it marshalled it correctly.
416 org.collectionspace.services.authorization.ObjectFactory objectFactory = new org.collectionspace.services.authorization.ObjectFactory();
417 toFile(objectFactory.createRolesList(rList), RolesList.class,
419 if (logger.isDebugEnabled()) {
420 logger.debug("exported roles to " + fileName);
424 public void exportDefaultPermissions(String fileName) {
425 PermissionsList pcList = new PermissionsList();
426 List<Permission> allPermList = new ArrayList<Permission>();
427 allPermList.addAll(adminPermList);
428 allPermList.addAll(readerPermList);
429 pcList.setPermission(allPermList);
430 org.collectionspace.services.authorization.ObjectFactory objectFactory =
431 new org.collectionspace.services.authorization.ObjectFactory();
432 toFile(pcList, PermissionsList.class,
433 // toFile(objectFactory.createPermissionsList(pcList), PermissionsList.class,
435 if (logger.isDebugEnabled()) {
436 logger.debug("exported permissions to " + fileName);
440 public void exportDefaultPermissionRoles(String fileName) {
441 PermissionsRolesList psrsl = new PermissionsRolesList();
442 List<PermissionRole> allPermRoleList = new ArrayList<PermissionRole>();
443 allPermRoleList.addAll(adminPermRoleList);
444 allPermRoleList.addAll(readerPermRoleList);
445 psrsl.setPermissionRole(allPermRoleList);
446 toFile(psrsl, PermissionsRolesList.class,
448 if (logger.isDebugEnabled()) {
449 logger.debug("exported permissions-roles to " + fileName);
453 private void toFile(Object o, Class jaxbClass, String fileName) {
454 File f = new File(fileName);
456 JAXBContext jc = JAXBContext.newInstance(jaxbClass);
457 Marshaller m = jc.createMarshaller();
458 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
461 } catch (Exception e) {