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 // Store the list of default roles, perms, and roleperms
91 private List<PermissionRole> allPermRoleList = null;
92 private List<Permission> allPermList;
93 private List<Role> allRoleList;
95 public void initialize(String tenantRootDirPath) throws Exception {
96 TenantBindingConfigReaderImpl tenantBindingConfigReader =
97 new TenantBindingConfigReaderImpl(tenantRootDirPath);
98 tenantBindingConfigReader.read();
99 tenantBindings = tenantBindingConfigReader.getTenantBindings();
100 cspaceAdminRole = buildCSpaceAdminRole();
102 if (logger.isDebugEnabled()) {
103 logger.debug("initialized with tenant bindings from " + tenantRootDirPath);
108 * createDefaultPermissions creates default admin and reader permissions
109 * for each tenant found in the given tenant binding file
113 public void createDefaultPermissions() {
114 for (String tenantId : tenantBindings.keySet()) {
115 List<Permission> adminPerms = createDefaultAdminPermissions(tenantId, AUTHZ_IS_ENTITY_PROXY);
116 adminPermList.addAll(adminPerms);
118 List<Permission> readerPerms = createDefaultReaderPermissions(tenantId, AUTHZ_IS_ENTITY_PROXY);
119 readerPermList.addAll(readerPerms);
124 * createDefaultAdminPermissions creates default admin permissions for all services
125 * used by the given tenant
129 public List<Permission> createDefaultAdminPermissions(String tenantId, boolean isEntityProxy) {
130 ArrayList<Permission> apcList = new ArrayList<Permission>();
131 TenantBindingType tbinding = tenantBindings.get(tenantId);
132 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
134 //add permissions for the main path
135 String resourceName = sbinding.getName().toLowerCase().trim();
136 if (isEntityProxy == true) {
137 resourceName = SecurityUtils.getResourceEntity(resourceName);
139 Permission perm = buildAdminPermission(tbinding.getId(),
143 //add permissions for alternate paths
144 if (isEntityProxy == false) {
145 List<String> uriPaths = sbinding.getUriPath();
146 for (String uriPath : uriPaths) {
147 perm = buildAdminPermission(tbinding.getId(),
148 uriPath.toLowerCase());
157 private Permission buildAdminPermission(String tenantId, String resourceName) {
158 String id = UUID.randomUUID().toString();
159 Permission perm = new Permission();
161 perm.setDescription("generated admin permission");
162 perm.setCreatedAtItem(new Date());
163 perm.setResourceName(resourceName.toLowerCase().trim());
164 perm.setEffect(EffectType.PERMIT);
165 perm.setTenantId(tenantId);
167 perm.setActionGroup(ACTIONGROUP_CRUDL);
168 ArrayList<PermissionAction> pas = new ArrayList<PermissionAction>();
171 PermissionAction permAction = PermissionActionUtil.create(perm, ActionType.CREATE);
174 permAction = PermissionActionUtil.create(perm, ActionType.READ);
177 permAction = PermissionActionUtil.create(perm, ActionType.UPDATE);
180 permAction = PermissionActionUtil.create(perm, ActionType.DELETE);
183 permAction = PermissionActionUtil.create(perm, ActionType.SEARCH);
190 * createDefaultReaderPermissions creates read only permissions for all services
191 * used by the given tenant
195 public List<Permission> createDefaultReaderPermissions(String tenantId, boolean isEntityProxy) {
196 ArrayList<Permission> apcList = new ArrayList<Permission>();
197 TenantBindingType tbinding = tenantBindings.get(tenantId);
198 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
199 //add permissions for the main path
200 String resourceName = sbinding.getName().toLowerCase().trim();
201 if (isEntityProxy == true) {
202 resourceName = SecurityUtils.getResourceEntity(resourceName);
204 Permission perm = buildReaderPermission(tbinding.getId(),
208 //add permissions for alternate paths
209 if (isEntityProxy == false) {
210 List<String> uriPaths = sbinding.getUriPath();
211 for (String uriPath : uriPaths) {
212 perm = buildReaderPermission(tbinding.getId(),
213 uriPath.toLowerCase());
222 private Permission buildReaderPermission(String tenantId, String resourceName) {
223 String id = UUID.randomUUID().toString();
224 Permission perm = new Permission();
226 perm.setCreatedAtItem(new Date());
227 perm.setDescription("generated readonly permission");
228 perm.setResourceName(resourceName.toLowerCase().trim());
229 perm.setEffect(EffectType.PERMIT);
230 perm.setTenantId(tenantId);
232 perm.setActionGroup(ACTIONGROUP_RL);
233 ArrayList<PermissionAction> pas = new ArrayList<PermissionAction>();
236 PermissionAction permAction = PermissionActionUtil.create(perm, ActionType.READ);
239 permAction = PermissionActionUtil.create(perm, ActionType.SEARCH);
245 public List<Permission> getDefaultPermissions() {
246 if (allPermList == null) {
247 allPermList = new ArrayList<Permission>();
248 allPermList.addAll(adminPermList);
249 allPermList.addAll(readerPermList);
254 public List<Permission> getDefaultAdminPermissions() {
255 return adminPermList;
258 public List<Permission> getDefaultReaderPermissions() {
259 return readerPermList;
263 * createDefaultRoles creates default admin and reader roles
264 * for each tenant found in the given tenant binding file
266 public void createDefaultRoles() {
267 for (String tenantId : tenantBindings.keySet()) {
269 Role arole = buildTenantAdminRole(tenantId);
270 adminRoles.add(arole);
272 Role rrole = buildTenantReaderRole(tenantId);
273 readerRoles.add(rrole);
277 private Role buildTenantAdminRole(String tenantId) {
278 return buildTenantRole(tenantId, ROLE_TENANT_ADMINISTRATOR, "admin");
281 private Role buildTenantReaderRole(String tenantId) {
282 return buildTenantRole(tenantId, ROLE_TENANT_READER, "read only");
285 private Role buildTenantRole(String tenantId, String name, String type) {
288 String roleName = ROLE_PREFIX + tenantId + "_" + name;
289 role = AuthorizationStore.getRoleByName(roleName, tenantId);
291 // the role doesn't exist already, so we need to create it
293 role.setCreatedAtItem(new Date());
294 role.setDisplayName(name);
295 role.setRoleName(roleName);
296 String id = UUID.randomUUID().toString();
298 role.setDescription("generated tenant " + type + " role");
299 role.setTenantId(tenantId);
300 role.setMetadataProtection(RoleClient.IMMUTABLE);
301 role.setPermsProtection(RoleClient.IMMUTABLE);
307 public List<Role> getDefaultRoles() {
308 if (allRoleList == null) {
309 allRoleList = new ArrayList<Role>();
310 allRoleList.addAll(adminRoles);
311 allRoleList.addAll(readerRoles);
316 public void associateDefaultPermissionsRoles() {
317 for (Permission p : adminPermList) {
318 PermissionRole permAdmRole = associatePermissionRoles(p, adminRoles, true);
319 adminPermRoleList.add(permAdmRole);
322 for (Permission p : readerPermList) {
323 PermissionRole permRdrRole = associatePermissionRoles(p, readerRoles, true);
324 readerPermRoleList.add(permRdrRole);
327 //CSpace Administrator has all access
328 List<Role> roles = new ArrayList<Role>();
329 roles.add(cspaceAdminRole);
330 for (Permission p : adminPermList) {
331 PermissionRole permCAdmRole = associatePermissionRoles(p, roles, false);
332 adminPermRoleList.add(permCAdmRole);
336 public List<PermissionRole> associatePermissionsRoles(List<Permission> perms, List<Role> roles, boolean enforceTenancy) {
337 List<PermissionRole> result = null;
339 List<PermissionRole> permRoles = new ArrayList<PermissionRole>();
340 for (Permission perm : perms) {
341 PermissionRole permRole = associatePermissionRoles(perm, roles, enforceTenancy);
342 if (permRole != null) {
343 permRoles.add(permRole);
347 if (permRoles.isEmpty() == false) {
354 private PermissionRole associatePermissionRoles(Permission perm,
355 List<Role> roles, boolean enforceTenancy) {
356 PermissionRole result = null;
358 PermissionRole pr = new PermissionRole();
359 pr.setSubject(SubjectType.ROLE);
360 List<PermissionValue> permValues = new ArrayList<PermissionValue>();
361 pr.setPermission(permValues);
362 PermissionValue permValue = new PermissionValue();
363 permValue.setPermissionId(perm.getCsid());
364 permValue.setResourceName(perm.getResourceName().toLowerCase());
365 permValue.setActionGroup(perm.getActionGroup());
366 permValues.add(permValue);
368 List<RoleValue> roleValues = new ArrayList<RoleValue>();
369 for (Role role : roles) {
370 boolean tenantIdsMatched = true;
371 if (enforceTenancy == true) {
372 tenantIdsMatched = role.getTenantId().equals(perm.getTenantId());
374 if (tenantIdsMatched == true) {
375 RoleValue rv = new RoleValue();
376 // This needs to use the qualified name, not the display name
377 rv.setRoleName(role.getRoleName().toUpperCase());
378 rv.setRoleId(role.getCsid());
381 if (logger.isTraceEnabled() == true) {
382 logger.trace("Role and Permission tenant ID did not match."); //FIXME: REM - Remove this debug statement.
387 // If 'roleValues' is not empty, then associate it with the incoming 'perm' values
388 // otherwise, return null;
390 if (roleValues.isEmpty() == false) {
391 pr.setRole(roleValues);
398 public List<PermissionRole> getDefaultPermissionRoles() {
399 if (allPermRoleList == null) {
400 allPermRoleList = new ArrayList<PermissionRole>();
401 allPermRoleList.addAll(adminPermRoleList);
402 allPermRoleList.addAll(readerPermRoleList);
404 return allPermRoleList;
407 public List<PermissionRole> getDefaultAdminPermissionRoles() {
408 return adminPermRoleList;
411 public List<PermissionRole> getDefaultReaderPermissionRoles() {
412 return readerPermRoleList;
415 private Role buildCSpaceAdminRole() {
416 Role role = new Role();
417 role.setDisplayName(ROLE_ADMINISTRATOR);
418 role.setRoleName(ROLE_PREFIX + role.getDisplayName());
419 role.setCsid(ROLE_ADMINISTRATOR_ID);
420 role.setTenantId(ADMINISTRATOR_TENANT_ID);
424 public void exportDefaultRoles(String fileName) {
425 RolesList rList = new RolesList();
426 rList.setRole(this.getDefaultRoles());
428 // Since it is missing the @XMLRootElement annotation, create a JAXBElement wrapper for the RoleList instance
429 // so we can have it marshalled it correctly.
431 org.collectionspace.services.authorization.ObjectFactory objectFactory = new org.collectionspace.services.authorization.ObjectFactory();
432 toFile(objectFactory.createRolesList(rList), RolesList.class,
434 if (logger.isDebugEnabled()) {
435 logger.debug("exported roles to " + fileName);
439 public void exportDefaultPermissions(String fileName) {
440 PermissionsList pcList = new PermissionsList();
441 pcList.setPermission(this.getDefaultPermissions());
442 org.collectionspace.services.authorization.ObjectFactory objectFactory =
443 new org.collectionspace.services.authorization.ObjectFactory();
444 toFile(pcList, PermissionsList.class,
445 // toFile(objectFactory.createPermissionsList(pcList), PermissionsList.class,
447 if (logger.isDebugEnabled()) {
448 logger.debug("exported permissions to " + fileName);
452 public void exportDefaultPermissionRoles(String fileName) {
453 PermissionsRolesList psrsl = new PermissionsRolesList();
454 psrsl.setPermissionRole(this.getDefaultAdminPermissionRoles());
455 toFile(psrsl, PermissionsRolesList.class,
457 if (logger.isDebugEnabled()) {
458 logger.debug("exported permissions-roles to " + fileName);
462 private void toFile(Object o, Class jaxbClass, String fileName) {
463 File f = new File(fileName);
465 JAXBContext jc = JAXBContext.newInstance(jaxbClass);
466 Marshaller m = jc.createMarshaller();
467 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
470 } catch (Exception e) {