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.Hashtable;
31 import java.util.List;
32 import javax.xml.bind.JAXBContext;
33 import javax.xml.bind.Marshaller;
34 import org.collectionspace.services.authorization.perms.Permission;
35 import org.collectionspace.authentication.AuthN;
36 import org.collectionspace.services.authorization.PermissionRole;
37 import org.collectionspace.services.authorization.PermissionValue;
38 import org.collectionspace.services.authorization.perms.PermissionsList;
39 import org.collectionspace.services.authorization.PermissionsRolesList;
40 import org.collectionspace.services.client.TenantClient;
41 import org.collectionspace.services.authorization.Role;
42 import org.collectionspace.services.authorization.RoleValue;
43 import org.collectionspace.services.authorization.RolesList;
44 import org.collectionspace.services.authorization.SubjectType;
45 import org.collectionspace.services.common.authorization_mgt.AuthorizationCommon;
46 import org.collectionspace.services.common.config.ServicesConfigReaderImpl;
47 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
48 import org.collectionspace.services.common.security.SecurityUtils;
49 import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
50 import org.collectionspace.services.config.service.ServiceBindingType;
51 import org.collectionspace.services.config.tenant.TenantBindingType;
54 * AuthorizationGen generates authorizations (permissions and roles)
58 public class AuthorizationGen {
59 final Logger logger = LoggerFactory.getLogger(AuthorizationGen.class);
61 // Should the base resource act as a proxy for its sub-resources for AuthZ purposes
63 final public static boolean AUTHZ_IS_ENTITY_PROXY = false;
65 final public static String TENANT_MGMNT_ID = "0";
67 private static final boolean USE_APP_GENERATED_BINDINGS = true;
69 private List<Permission> readWritePermList = new ArrayList<Permission>();
70 private List<Permission> tenantMgmntPermList = new ArrayList<Permission>();
71 private List<PermissionRole> tenantMgmntPermRoleList = new ArrayList<PermissionRole>();
73 private List<Permission> adminPermList = new ArrayList<Permission>();
74 private List<PermissionRole> adminPermRoleList = new ArrayList<PermissionRole>();
76 private List<Permission> readerPermList = new ArrayList<Permission>();
77 private List<PermissionRole> readerPermRoleList = new ArrayList<PermissionRole>();
79 private List<Role> adminRoles = new ArrayList<Role>();
80 private List<Role> readerRoles = new ArrayList<Role>();
82 private Role cspaceTenantMgmntRole;
83 private Hashtable<String, TenantBindingType> tenantBindings = new Hashtable<String, TenantBindingType>();
85 // Store the list of default roles, perms, and roleperms
87 private List<PermissionRole> allPermRoleList = null;
88 private List<Permission> allPermList;
89 private List<Role> allRoleList;
91 public void initialize(String tenantRootDirPath) throws Exception {
92 ServicesConfigReaderImpl servicesConfigReader = new ServicesConfigReaderImpl(tenantRootDirPath);
93 servicesConfigReader.read(USE_APP_GENERATED_BINDINGS);
94 Boolean useAppGeneratedBindings = servicesConfigReader.getConfiguration().isUseAppGeneratedTenantBindings();
96 TenantBindingConfigReaderImpl tenantBindingConfigReader =
97 new TenantBindingConfigReaderImpl(tenantRootDirPath);
98 tenantBindingConfigReader.read(useAppGeneratedBindings);
99 // Note that we build permissions for all tenants, whether or not they are marked create disabled.
100 // This is a hack until we can correctly run an incremental import.
101 tenantBindings = tenantBindingConfigReader.getTenantBindings(
102 TenantBindingConfigReaderImpl.INCLUDE_CREATE_DISABLED_TENANTS);
103 cspaceTenantMgmntRole = buildTenantMgmntRole();
105 if (logger.isDebugEnabled()) {
106 logger.debug("initialized with tenant bindings from " + tenantRootDirPath);
111 * createDefaultPermissions creates default admin and reader permissions
112 * for each tenant found in the given tenant binding file
116 public void createDefaultPermissions(JPATransactionContext jpaTransactionContext) {
117 for (String tenantId : tenantBindings.keySet()) {
118 List<Permission> adminPerms = createDefaultAdminPermissions(tenantId, AUTHZ_IS_ENTITY_PROXY); // CRUDL perms
119 adminPermList.addAll(adminPerms);
121 List<Permission> readerPerms = createDefaultReaderPermissions(tenantId, AUTHZ_IS_ENTITY_PROXY); // RL perms
122 readerPermList.addAll(readerPerms);
124 List<Permission> readWritePerms = createDefaultReadWritePermissions(tenantId, AUTHZ_IS_ENTITY_PROXY); // CRUL perms
125 readWritePermList.addAll(readWritePerms);
128 List<Permission> tenantMgmntPerms = createDefaultTenantMgmntPermissions();
129 tenantMgmntPermList.addAll(tenantMgmntPerms);
133 * createDefaultAdminPermissions creates default admin permissions for all services
134 * used by the given tenant
138 public List<Permission> createDefaultAdminPermissions(String tenantId, boolean isEntityProxy) {
139 ArrayList<Permission> result = new ArrayList<Permission>();
140 TenantBindingType tbinding = tenantBindings.get(tenantId);
141 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
143 //add permissions for the main path
144 String resourceName = sbinding.getName().toLowerCase().trim();
145 if (isEntityProxy == true) {
146 resourceName = SecurityUtils.getResourceEntity(resourceName);
148 Permission perm = buildAdminPermission(tbinding.getId(), resourceName);
151 //add permissions for alternate paths
152 if (isEntityProxy == false) {
153 List<String> uriPaths = sbinding.getUriPath();
154 for (String uriPath : uriPaths) {
155 perm = buildAdminPermission(tbinding.getId(), uriPath.toLowerCase());
165 * createDefaultTenantMgmntPermissions creates default permissions for known
166 * Tenant Mgmnt services.
169 public List<Permission> createDefaultTenantMgmntPermissions() {
170 ArrayList<Permission> apcList = new ArrayList<Permission>();
171 // Later can think about ways to configure this if we want to
172 Permission perm = createTenantMgmntPermission(TenantClient.SERVICE_NAME);
179 * createTenantMgmntPermission creates special admin permissions for tenant management
182 private Permission createTenantMgmntPermission(String resourceName) {
183 Permission perm = buildAdminPermission(TENANT_MGMNT_ID, resourceName);
188 * createDefaultReadWritePermissions creates read-write (CRUL) permissions for all services
189 * used by the given tenant
193 public List<Permission> createDefaultReadWritePermissions(String tenantId, boolean isEntityProxy) {
194 ArrayList<Permission> apcList = new ArrayList<Permission>();
196 TenantBindingType tbinding = tenantBindings.get(tenantId);
197 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
198 //add permissions for the main path
199 String resourceName = sbinding.getName().toLowerCase().trim();
200 if (isEntityProxy == true) {
201 resourceName = SecurityUtils.getResourceEntity(resourceName);
203 Permission perm = buildReadWritePermission(tbinding.getId(), resourceName);
206 //add permissions for alternate paths
207 if (isEntityProxy == false) {
208 List<String> uriPaths = sbinding.getUriPath();
209 for (String uriPath : uriPaths) {
210 perm = buildReadWritePermission(tbinding.getId(), uriPath.toLowerCase());
220 * createDefaultReaderPermissions creates read only permissions for all services
221 * used by the given tenant
226 public List<Permission> createDefaultReaderPermissions(String tenantId, boolean isEntityProxy) {
227 ArrayList<Permission> apcList = new ArrayList<Permission>();
229 TenantBindingType tbinding = tenantBindings.get(tenantId);
230 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
231 //add permissions for the main path
232 String resourceName = sbinding.getName().toLowerCase().trim();
233 if (isEntityProxy == true) {
234 resourceName = SecurityUtils.getResourceEntity(resourceName);
236 Permission perm = buildReaderPermission(tbinding.getId(), resourceName);
239 //add permissions for alternate paths
240 if (isEntityProxy == false) {
241 List<String> uriPaths = sbinding.getUriPath();
242 for (String uriPath : uriPaths) {
243 perm = buildReaderPermission(tbinding.getId(), uriPath.toLowerCase());
252 private Permission buildAdminPermission(String tenantId, String resourceName) {
253 String description = "Generated admin permission.";
254 return AuthorizationCommon.createPermission(tenantId, resourceName, description, AuthorizationCommon.ACTIONGROUP_CRUDL_NAME, true);
257 private Permission buildReaderPermission(String tenantId, String resourceName) {
258 String description = "Generated read-only (RL) permission.";
259 return AuthorizationCommon.createPermission(tenantId, resourceName, description, AuthorizationCommon.ACTIONGROUP_RL_NAME, true);
262 private Permission buildReadWritePermission(String tenantId, String resourceName) {
263 String description = "Generated read-write (CRUL) permission.";
264 return AuthorizationCommon.createPermission(tenantId, resourceName, description, AuthorizationCommon.ACTIONGROUP_CRUL_NAME, true);
267 public List<Permission> getDefaultPermissions() {
268 if (allPermList == null) {
269 allPermList = new ArrayList<Permission>();
270 allPermList.addAll(adminPermList);
271 allPermList.addAll(readerPermList);
272 allPermList.addAll(readWritePermList);
273 allPermList.addAll(tenantMgmntPermList);
278 public List<Permission> getDefaultAdminPermissions() {
279 return adminPermList;
282 public List<Permission> getDefaultReaderPermissions() {
283 return readerPermList;
286 public List<Permission> getDefaultTenantMgmntPermissions() {
287 return tenantMgmntPermList;
291 * createDefaultRoles creates default admin and reader roles
292 * for each tenant found in the given tenant binding file
294 public void createDefaultRoles(JPATransactionContext jpaTransactionContext) {
295 for (String tenantId : tenantBindings.keySet()) {
297 Role arole = buildTenantAdminRole(jpaTransactionContext, tenantId);
298 adminRoles.add(arole);
300 Role rrole = buildTenantReaderRole(jpaTransactionContext, tenantId);
301 readerRoles.add(rrole);
305 private Role buildTenantAdminRole(JPATransactionContext jpaTransactionContext, String tenantId) {
306 String type = "admin";
307 Role result = AuthorizationCommon.getRole(jpaTransactionContext, tenantId, AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR);
309 if (result == null) {
310 // the role doesn't exist already, so we need to create it
311 String description = "Generated tenant " + type + " role.";
312 result = AuthorizationCommon.createRole(tenantId, AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR, description, true /*immutable*/);
318 private Role buildTenantReaderRole(JPATransactionContext jpaTransactionContext, String tenantId) {
319 String type = "read only";
320 Role result = AuthorizationCommon.getRole(jpaTransactionContext, tenantId, AuthorizationCommon.ROLE_TENANT_READER);
322 if (result == null) {
323 // the role doesn't exist already, so we need to create it
324 String description = "Generated tenant " + type + " role.";
325 result = AuthorizationCommon.createRole(tenantId, AuthorizationCommon.ROLE_TENANT_READER, description, true /*immutable*/);
332 public List<Role> getDefaultRoles() {
333 if (allRoleList == null) {
334 allRoleList = new ArrayList<Role>();
335 allRoleList.addAll(adminRoles);
336 allRoleList.addAll(readerRoles);
337 // Finally, add the tenant manager role to the list
338 allRoleList.add(cspaceTenantMgmntRole);
343 public void associateDefaultPermissionsRoles() {
344 for (Permission p : adminPermList) {
345 PermissionRole permAdmRole = associatePermissionToRoles(p, adminRoles, true);
346 adminPermRoleList.add(permAdmRole);
349 for (Permission p : readerPermList) {
350 PermissionRole permRdrRole = associatePermissionToRoles(p, readerRoles, true);
351 readerPermRoleList.add(permRdrRole);
354 //CSpace Tenant Manager has all access
355 // PLS - this looks wrong. This should be a tenantMgmnt role, and only have access to
356 // tenantMgmnt perms. Will leave this for now...
357 List<Role> roles = new ArrayList<Role>();
358 roles.add(cspaceTenantMgmntRole);
359 /* for (Permission p : adminPermList) {
360 PermissionRole permCAdmRole = associatePermissionRoles(p, roles, false);
361 adminPermRoleList.add(permCAdmRole);
364 // Now associate the tenant management perms to the role
365 for (Permission p : tenantMgmntPermList) {
366 // Note we enforce tenant, as should all be tenant 0 (the special one)
367 PermissionRole permTMRole = associatePermissionToRoles(p, roles, true);
368 tenantMgmntPermRoleList.add(permTMRole);
373 public List<PermissionRole> associatePermissionsRoles(List<Permission> perms, List<Role> roles, boolean enforceTenancy) {
374 List<PermissionRole> result = null;
376 List<PermissionRole> permRoles = new ArrayList<PermissionRole>();
377 for (Permission perm : perms) {
378 PermissionRole permRole = associatePermissionToRoles(perm, roles, enforceTenancy);
379 if (permRole != null) {
380 permRoles.add(permRole);
384 if (permRoles.isEmpty() == false) {
391 private PermissionRole associatePermissionToRoles(Permission perm,
392 List<Role> roles, boolean enforceTenancy) {
393 PermissionRole result = null;
395 PermissionRole pr = new PermissionRole();
396 pr.setSubject(SubjectType.ROLE);
397 List<PermissionValue> permValueList = new ArrayList<PermissionValue>();
398 pr.setPermission(permValueList);
400 PermissionValue permValue = new PermissionValue();
401 permValue.setPermissionId(perm.getCsid());
402 permValue.setResourceName(perm.getResourceName().toLowerCase());
403 permValue.setActionGroup(perm.getActionGroup());
404 permValue.setTenantId(perm.getTenantId());
405 permValueList.add(permValue);
407 List<RoleValue> roleValues = new ArrayList<RoleValue>();
408 for (Role role : roles) {
409 boolean tenantIdsMatched = true;
410 if (enforceTenancy == true) {
411 tenantIdsMatched = role.getTenantId().equals(perm.getTenantId());
413 if (tenantIdsMatched == true) {
414 RoleValue rv = new RoleValue();
415 // This needs to use the qualified name, not the display name
416 rv.setRoleName(role.getRoleName().toUpperCase());
417 rv.setRoleId(role.getCsid());
418 rv.setTenantId(role.getTenantId());
421 if (logger.isTraceEnabled() == true) {
422 logger.trace("Role and Permission tenant ID did not match."); //FIXME: REM - Remove this debug statement.
427 // If 'roleValues' is not empty, then associate it with the incoming 'perm' values
428 // otherwise, return null;
430 if (roleValues.isEmpty() == false) {
431 pr.setRole(roleValues);
438 public List<PermissionRole> getDefaultPermissionRoles() {
439 if (allPermRoleList == null) {
440 allPermRoleList = new ArrayList<PermissionRole>();
441 allPermRoleList.addAll(adminPermRoleList);
442 allPermRoleList.addAll(readerPermRoleList);
443 allPermRoleList.addAll(tenantMgmntPermRoleList);
445 return allPermRoleList;
448 public List<PermissionRole> getDefaultAdminPermissionRoles() {
449 return adminPermRoleList;
452 public List<PermissionRole> getDefaultReaderPermissionRoles() {
453 return readerPermRoleList;
456 private Role buildTenantMgmntRole() {
457 Role role = new Role();
459 role.setDescription("A generated super role that has permissions to manage tenants.");
460 role.setDisplayName(AuthN.ROLE_ALL_TENANTS_MANAGER);
461 role.setRoleName(AuthorizationCommon.getQualifiedRoleName(
462 AuthN.ALL_TENANTS_MANAGER_TENANT_ID, role.getDisplayName()));
463 role.setCsid(AuthN.ROLE_ALL_TENANTS_MANAGER_ID);
464 role.setTenantId(AuthN.ALL_TENANTS_MANAGER_TENANT_ID);
470 public void exportDefaultRoles(String fileName) {
471 RolesList rList = new RolesList();
472 rList.setRole(this.getDefaultRoles());
474 // Since it is missing the @XMLRootElement annotation, create a JAXBElement wrapper for the RoleList instance
475 // so we can have it marshalled it correctly.
477 org.collectionspace.services.authorization.ObjectFactory objectFactory = new org.collectionspace.services.authorization.ObjectFactory();
478 toFile(objectFactory.createRolesList(rList), RolesList.class,
480 if (logger.isDebugEnabled()) {
481 logger.debug("exported roles to " + fileName);
485 public void exportDefaultPermissions(String fileName) {
486 PermissionsList pcList = new PermissionsList();
487 pcList.setPermission(this.getDefaultPermissions());
488 org.collectionspace.services.authorization.ObjectFactory objectFactory =
489 new org.collectionspace.services.authorization.ObjectFactory();
490 toFile(pcList, PermissionsList.class,
491 // toFile(objectFactory.createPermissionsList(pcList), PermissionsList.class,
493 if (logger.isDebugEnabled()) {
494 logger.debug("exported permissions to " + fileName);
498 public void exportDefaultPermissionRoles(String fileName) {
499 PermissionsRolesList psrsl = new PermissionsRolesList();
500 psrsl.setPermissionRole(this.getDefaultAdminPermissionRoles());
501 toFile(psrsl, PermissionsRolesList.class,
503 if (logger.isDebugEnabled()) {
504 logger.debug("exported permissions-roles to " + fileName);
508 private void toFile(Object o, Class jaxbClass, String fileName) {
509 File f = new File(fileName);
511 JAXBContext jc = JAXBContext.newInstance(jaxbClass);
512 Marshaller m = jc.createMarshaller();
513 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
516 } catch (Exception e) {