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;
30 import java.util.ArrayList;
31 import java.util.Hashtable;
32 import java.util.List;
33 import javax.xml.bind.JAXBContext;
34 import javax.xml.bind.Marshaller;
36 import org.collectionspace.services.client.TenantClient;
37 import org.collectionspace.authentication.AuthN;
38 import org.collectionspace.authentication.AuthN;
40 import org.collectionspace.services.authorization.perms.Permission;
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;
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;
51 import org.collectionspace.services.common.authorization_mgt.AuthorizationCommon;
52 import org.collectionspace.services.common.config.ServicesConfigReaderImpl;
53 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
54 import org.collectionspace.services.common.security.SecurityUtils;
55 import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
57 import org.collectionspace.services.config.service.ServiceBindingType;
58 import org.collectionspace.services.config.tenant.TenantBindingType;
61 * AuthorizationGen generates authorizations (permissions and roles)
65 public class AuthorizationGen {
66 final Logger logger = LoggerFactory.getLogger(AuthorizationGen.class);
68 // Should the base resource act as a proxy for its sub-resources for AuthZ purposes
70 final public static boolean AUTHZ_IS_ENTITY_PROXY = false;
72 final public static String TENANT_MGMNT_ID = "0";
74 private static final boolean USE_APP_GENERATED_BINDINGS = true;
76 private List<Permission> readWritePermList = new ArrayList<Permission>();
77 private List<Permission> tenantMgmntPermList = new ArrayList<Permission>();
78 private List<PermissionRole> tenantMgmntPermRoleList = new ArrayList<PermissionRole>();
80 private List<Permission> adminPermList = new ArrayList<Permission>();
81 private List<PermissionRole> adminPermRoleList = new ArrayList<PermissionRole>();
83 private List<Permission> readerPermList = new ArrayList<Permission>();
84 private List<PermissionRole> readerPermRoleList = new ArrayList<PermissionRole>();
86 private List<Role> adminRoles = new ArrayList<Role>();
87 private List<Role> readerRoles = new ArrayList<Role>();
89 private Role cspaceTenantMgmntRole;
90 private Hashtable<String, TenantBindingType> tenantBindings = new Hashtable<String, TenantBindingType>();
92 // Store the list of default roles, perms, and roleperms
94 private List<PermissionRole> allPermRoleList = null;
95 private List<Permission> allPermList;
96 private List<Role> allRoleList;
98 public void initialize(String tenantRootDirPath) throws Exception {
99 ServicesConfigReaderImpl servicesConfigReader = new ServicesConfigReaderImpl(tenantRootDirPath);
100 servicesConfigReader.read(USE_APP_GENERATED_BINDINGS);
101 Boolean useAppGeneratedBindings = servicesConfigReader.getConfiguration().isUseAppGeneratedTenantBindings();
103 TenantBindingConfigReaderImpl tenantBindingConfigReader =
104 new TenantBindingConfigReaderImpl(tenantRootDirPath);
105 tenantBindingConfigReader.read(useAppGeneratedBindings);
108 // Don't include disabled tenants
110 tenantBindings = tenantBindingConfigReader.getTenantBindings( TenantBindingConfigReaderImpl.EXCLUDE_CREATE_DISABLED_TENANTS);
111 cspaceTenantMgmntRole = buildTenantMgmntRole();
113 if (logger.isDebugEnabled()) {
114 logger.debug("initialized with tenant bindings from " + tenantRootDirPath);
119 * createDefaultPermissions creates default admin and reader permissions
120 * for each tenant found in the given tenant binding file
124 public void createDefaultPermissions(JPATransactionContext jpaTransactionContext) {
125 for (String tenantId : tenantBindings.keySet()) {
126 List<Permission> adminPerms = createDefaultAdminPermissions(tenantId, AUTHZ_IS_ENTITY_PROXY); // CRUDL perms
127 adminPermList.addAll(adminPerms);
129 List<Permission> readerPerms = createDefaultReaderPermissions(tenantId, AUTHZ_IS_ENTITY_PROXY); // RL perms
130 readerPermList.addAll(readerPerms);
132 List<Permission> readWritePerms = createDefaultReadWritePermissions(tenantId, AUTHZ_IS_ENTITY_PROXY); // CRUL perms
133 readWritePermList.addAll(readWritePerms);
136 List<Permission> tenantMgmntPerms = createDefaultTenantMgmntPermissions();
137 tenantMgmntPermList.addAll(tenantMgmntPerms);
141 * createDefaultAdminPermissions creates default admin permissions for all services
142 * used by the given tenant
146 public List<Permission> createDefaultAdminPermissions(String tenantId, boolean isEntityProxy) {
147 ArrayList<Permission> result = new ArrayList<Permission>();
148 TenantBindingType tbinding = tenantBindings.get(tenantId);
149 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
151 //add permissions for the main path
152 String resourceName = sbinding.getName().toLowerCase().trim();
153 if (isEntityProxy == true) {
154 resourceName = SecurityUtils.getResourceEntity(resourceName);
156 Permission perm = buildAdminPermission(tbinding.getId(), resourceName);
159 //add permissions for alternate paths
160 if (isEntityProxy == false) {
161 List<String> uriPaths = sbinding.getUriPath();
162 for (String uriPath : uriPaths) {
163 perm = buildAdminPermission(tbinding.getId(), uriPath.toLowerCase());
173 * createDefaultTenantMgmntPermissions creates default permissions for known
174 * Tenant Mgmnt services.
177 public List<Permission> createDefaultTenantMgmntPermissions() {
178 ArrayList<Permission> apcList = new ArrayList<Permission>();
179 // Later can think about ways to configure this if we want to
180 Permission perm = createTenantMgmntPermission(TenantClient.SERVICE_NAME);
187 * createTenantMgmntPermission creates special admin permissions for tenant management
190 private Permission createTenantMgmntPermission(String resourceName) {
191 Permission perm = buildAdminPermission(TENANT_MGMNT_ID, resourceName);
196 * createDefaultReadWritePermissions creates read-write (CRUL) permissions for all services
197 * used by the given tenant
201 public List<Permission> createDefaultReadWritePermissions(String tenantId, boolean isEntityProxy) {
202 ArrayList<Permission> apcList = new ArrayList<Permission>();
204 TenantBindingType tbinding = tenantBindings.get(tenantId);
205 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
206 //add permissions for the main path
207 String resourceName = sbinding.getName().toLowerCase().trim();
208 if (isEntityProxy == true) {
209 resourceName = SecurityUtils.getResourceEntity(resourceName);
211 Permission perm = buildReadWritePermission(tbinding.getId(), resourceName);
214 //add permissions for alternate paths
215 if (isEntityProxy == false) {
216 List<String> uriPaths = sbinding.getUriPath();
217 for (String uriPath : uriPaths) {
218 perm = buildReadWritePermission(tbinding.getId(), uriPath.toLowerCase());
228 * createDefaultReaderPermissions creates read only permissions for all services
229 * used by the given tenant
234 public List<Permission> createDefaultReaderPermissions(String tenantId, boolean isEntityProxy) {
235 ArrayList<Permission> apcList = new ArrayList<Permission>();
237 TenantBindingType tbinding = tenantBindings.get(tenantId);
238 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
239 //add permissions for the main path
240 String resourceName = sbinding.getName().toLowerCase().trim();
241 if (isEntityProxy == true) {
242 resourceName = SecurityUtils.getResourceEntity(resourceName);
244 Permission perm = buildReaderPermission(tbinding.getId(), resourceName);
247 //add permissions for alternate paths
248 if (isEntityProxy == false) {
249 List<String> uriPaths = sbinding.getUriPath();
250 for (String uriPath : uriPaths) {
251 perm = buildReaderPermission(tbinding.getId(), uriPath.toLowerCase());
260 private Permission buildAdminPermission(String tenantId, String resourceName) {
261 String description = AuthN.GENERATED_STR + "admin permission.";
262 return AuthorizationCommon.createPermission(tenantId, resourceName, description, AuthorizationCommon.ACTIONGROUP_CRUDL_NAME, true);
265 private Permission buildReaderPermission(String tenantId, String resourceName) {
266 String description = AuthN.GENERATED_STR + "read-only (RL) permission.";
267 return AuthorizationCommon.createPermission(tenantId, resourceName, description, AuthorizationCommon.ACTIONGROUP_RL_NAME, true);
270 private Permission buildReadWritePermission(String tenantId, String resourceName) {
271 String description = AuthN.GENERATED_STR + "read-write (CRUL) permission.";
272 return AuthorizationCommon.createPermission(tenantId, resourceName, description, AuthorizationCommon.ACTIONGROUP_CRUL_NAME, true);
275 public List<Permission> getDefaultPermissions() {
276 if (allPermList == null) {
277 allPermList = new ArrayList<Permission>();
278 allPermList.addAll(adminPermList);
279 allPermList.addAll(readerPermList);
280 allPermList.addAll(readWritePermList);
281 allPermList.addAll(tenantMgmntPermList);
286 public List<Permission> getDefaultAdminPermissions() {
287 return adminPermList;
290 public List<Permission> getDefaultReaderPermissions() {
291 return readerPermList;
294 public List<Permission> getDefaultTenantMgmntPermissions() {
295 return tenantMgmntPermList;
299 * createDefaultRoles creates default admin and reader roles
300 * for each tenant found in the given tenant binding file
302 public void createDefaultRoles(JPATransactionContext jpaTransactionContext) {
303 for (String tenantId : tenantBindings.keySet()) {
305 Role arole = buildTenantAdminRole(jpaTransactionContext, tenantId);
306 adminRoles.add(arole);
308 Role rrole = buildTenantReaderRole(jpaTransactionContext, tenantId);
309 readerRoles.add(rrole);
313 private Role buildTenantAdminRole(JPATransactionContext jpaTransactionContext, String tenantId) {
314 String type = "admin";
315 Role result = AuthorizationCommon.getRole(jpaTransactionContext, tenantId, AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR);
317 if (result == null) {
318 // the role doesn't exist already, so we need to create it
319 String description = "Generated tenant " + type + " role.";
320 result = AuthorizationCommon.createRole(tenantId, AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR, description, true /*immutable*/);
326 private Role buildTenantReaderRole(JPATransactionContext jpaTransactionContext, String tenantId) {
327 String type = "read only";
328 Role result = AuthorizationCommon.getRole(jpaTransactionContext, tenantId, AuthorizationCommon.ROLE_TENANT_READER);
330 if (result == null) {
331 // the role doesn't exist already, so we need to create it
332 String description = "Generated tenant " + type + " role.";
333 result = AuthorizationCommon.createRole(tenantId, AuthorizationCommon.ROLE_TENANT_READER, description, true /*immutable*/);
340 public List<Role> getDefaultRoles() {
341 if (allRoleList == null) {
342 allRoleList = new ArrayList<Role>();
343 allRoleList.addAll(adminRoles);
344 allRoleList.addAll(readerRoles);
345 // Finally, add the tenant manager role to the list
346 allRoleList.add(cspaceTenantMgmntRole);
351 public void associateDefaultPermissionsRoles() {
352 for (Permission p : adminPermList) {
353 PermissionRole permAdmRole = associatePermissionToRoles(p, adminRoles, true);
354 adminPermRoleList.add(permAdmRole);
357 for (Permission p : readerPermList) {
358 PermissionRole permRdrRole = associatePermissionToRoles(p, readerRoles, true);
359 readerPermRoleList.add(permRdrRole);
362 //CSpace Tenant Manager has all access
363 // PLS - this looks wrong. This should be a tenantMgmnt role, and only have access to
364 // tenantMgmnt perms. Will leave this for now...
365 List<Role> roles = new ArrayList<Role>();
366 roles.add(cspaceTenantMgmntRole);
367 /* for (Permission p : adminPermList) {
368 PermissionRole permCAdmRole = associatePermissionRoles(p, roles, false);
369 adminPermRoleList.add(permCAdmRole);
372 // Now associate the tenant management perms to the role
373 for (Permission p : tenantMgmntPermList) {
374 // Note we enforce tenant, as should all be tenant 0 (the special one)
375 PermissionRole permTMRole = associatePermissionToRoles(p, roles, true);
376 tenantMgmntPermRoleList.add(permTMRole);
381 public List<PermissionRole> associatePermissionsRoles(List<Permission> perms, List<Role> roles, boolean enforceTenancy) {
382 List<PermissionRole> result = null;
384 List<PermissionRole> permRoles = new ArrayList<PermissionRole>();
385 for (Permission perm : perms) {
386 PermissionRole permRole = associatePermissionToRoles(perm, roles, enforceTenancy);
387 if (permRole != null) {
388 permRoles.add(permRole);
392 if (permRoles.isEmpty() == false) {
399 private PermissionRole associatePermissionToRoles(Permission perm,
400 List<Role> roles, boolean enforceTenancy) {
401 PermissionRole result = null;
403 PermissionRole pr = new PermissionRole();
404 pr.setSubject(SubjectType.ROLE);
405 List<PermissionValue> permValueList = new ArrayList<PermissionValue>();
406 pr.setPermission(permValueList);
408 PermissionValue permValue = new PermissionValue();
409 permValue.setPermissionId(perm.getCsid());
410 permValue.setResourceName(perm.getResourceName().toLowerCase());
411 permValue.setActionGroup(perm.getActionGroup());
412 permValue.setTenantId(perm.getTenantId());
413 permValueList.add(permValue);
415 List<RoleValue> roleValues = new ArrayList<RoleValue>();
416 for (Role role : roles) {
417 boolean tenantIdsMatched = true;
418 if (enforceTenancy == true) {
419 tenantIdsMatched = role.getTenantId().equals(perm.getTenantId());
421 if (tenantIdsMatched == true) {
422 RoleValue rv = new RoleValue();
423 // This needs to use the qualified name, not the display name
424 rv.setRoleName(role.getRoleName().toUpperCase());
425 rv.setRoleId(role.getCsid());
426 rv.setTenantId(role.getTenantId());
429 if (logger.isTraceEnabled() == true) {
430 logger.trace("Role and Permission tenant ID did not match."); //FIXME: REM - Remove this debug statement.
435 // If 'roleValues' is not empty, then associate it with the incoming 'perm' values
436 // otherwise, return null;
438 if (roleValues.isEmpty() == false) {
439 pr.setRole(roleValues);
446 public List<PermissionRole> getDefaultPermissionRoles() {
447 if (allPermRoleList == null) {
448 allPermRoleList = new ArrayList<PermissionRole>();
449 allPermRoleList.addAll(adminPermRoleList);
450 allPermRoleList.addAll(readerPermRoleList);
451 allPermRoleList.addAll(tenantMgmntPermRoleList);
453 return allPermRoleList;
456 public List<PermissionRole> getDefaultAdminPermissionRoles() {
457 return adminPermRoleList;
460 public List<PermissionRole> getDefaultReaderPermissionRoles() {
461 return readerPermRoleList;
464 private Role buildTenantMgmntRole() {
465 Role role = new Role();
467 role.setDescription("A generated super role that has permissions to manage tenants.");
468 role.setDisplayName(AuthN.ROLE_ALL_TENANTS_MANAGER);
469 role.setRoleName(AuthorizationCommon.getQualifiedRoleName(
470 AuthN.ALL_TENANTS_MANAGER_TENANT_ID, role.getDisplayName()));
471 role.setCsid(AuthN.ROLE_ALL_TENANTS_MANAGER_ID);
472 role.setTenantId(AuthN.ALL_TENANTS_MANAGER_TENANT_ID);
478 public void exportDefaultRoles(String fileName) {
479 RolesList rList = new RolesList();
480 rList.setRole(this.getDefaultRoles());
482 // Since it is missing the @XMLRootElement annotation, create a JAXBElement wrapper for the RoleList instance
483 // so we can have it marshalled it correctly.
485 org.collectionspace.services.authorization.ObjectFactory objectFactory = new org.collectionspace.services.authorization.ObjectFactory();
486 toFile(objectFactory.createRolesList(rList), RolesList.class,
488 if (logger.isDebugEnabled()) {
489 logger.debug("exported roles to " + fileName);
493 public void exportDefaultPermissions(String fileName) {
494 PermissionsList pcList = new PermissionsList();
495 pcList.setPermission(this.getDefaultPermissions());
496 org.collectionspace.services.authorization.ObjectFactory objectFactory =
497 new org.collectionspace.services.authorization.ObjectFactory();
498 toFile(pcList, PermissionsList.class,
499 // toFile(objectFactory.createPermissionsList(pcList), PermissionsList.class,
501 if (logger.isDebugEnabled()) {
502 logger.debug("exported permissions to " + fileName);
506 public void exportDefaultPermissionRoles(String fileName) {
507 PermissionsRolesList psrsl = new PermissionsRolesList();
508 psrsl.setPermissionRole(this.getDefaultAdminPermissionRoles());
509 toFile(psrsl, PermissionsRolesList.class,
511 if (logger.isDebugEnabled()) {
512 logger.debug("exported permissions-roles to " + fileName);
516 private void toFile(Object o, Class jaxbClass, String fileName) {
517 File f = new File(fileName);
519 JAXBContext jc = JAXBContext.newInstance(jaxbClass);
520 Marshaller m = jc.createMarshaller();
521 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
524 } catch (Exception e) {