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.authorization_mgt.AuthorizationCommon;
51 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
52 import org.collectionspace.services.common.security.SecurityUtils;
53 import org.collectionspace.services.config.service.ServiceBindingType;
54 import org.collectionspace.services.config.tenant.TenantBindingType;
57 * AuthorizationGen generates authorizations (permissions and roles)
61 public class AuthorizationGen {
64 // Should the base resource act as a proxy for its sub-resources for AuthZ purposes
66 final public static boolean AUTHZ_IS_ENTITY_PROXY = false;
68 final Logger logger = LoggerFactory.getLogger(AuthorizationGen.class);
69 private List<Permission> adminPermList = new ArrayList<Permission>();
70 private List<PermissionRole> adminPermRoleList = new ArrayList<PermissionRole>();
71 private List<Permission> readerPermList = new ArrayList<Permission>();
72 private List<PermissionRole> readerPermRoleList = new ArrayList<PermissionRole>();
73 private List<Role> adminRoles = new ArrayList<Role>();
74 private List<Role> readerRoles = new ArrayList<Role>();
75 private Role cspaceAdminRole;
76 private Hashtable<String, TenantBindingType> tenantBindings =
77 new Hashtable<String, TenantBindingType>();
79 // Store the list of default roles, perms, and roleperms
81 private List<PermissionRole> allPermRoleList = null;
82 private List<Permission> allPermList;
83 private List<Role> allRoleList;
85 public void initialize(String tenantRootDirPath) throws Exception {
86 TenantBindingConfigReaderImpl tenantBindingConfigReader =
87 new TenantBindingConfigReaderImpl(tenantRootDirPath);
88 tenantBindingConfigReader.read();
89 tenantBindings = tenantBindingConfigReader.getTenantBindings();
90 cspaceAdminRole = buildCSpaceAdminRole();
92 if (logger.isDebugEnabled()) {
93 logger.debug("initialized with tenant bindings from " + tenantRootDirPath);
98 * createDefaultPermissions creates default admin and reader permissions
99 * for each tenant found in the given tenant binding file
103 public void createDefaultPermissions() {
104 for (String tenantId : tenantBindings.keySet()) {
105 List<Permission> adminPerms = createDefaultAdminPermissions(tenantId, AUTHZ_IS_ENTITY_PROXY);
106 adminPermList.addAll(adminPerms);
108 List<Permission> readerPerms = createDefaultReaderPermissions(tenantId, AUTHZ_IS_ENTITY_PROXY);
109 readerPermList.addAll(readerPerms);
114 * createDefaultAdminPermissions creates default admin permissions for all services
115 * used by the given tenant
119 public List<Permission> createDefaultAdminPermissions(String tenantId, boolean isEntityProxy) {
120 ArrayList<Permission> apcList = new ArrayList<Permission>();
121 TenantBindingType tbinding = tenantBindings.get(tenantId);
122 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
124 //add permissions for the main path
125 String resourceName = sbinding.getName().toLowerCase().trim();
126 if (isEntityProxy == true) {
127 resourceName = SecurityUtils.getResourceEntity(resourceName);
129 Permission perm = buildAdminPermission(tbinding.getId(),
133 //add permissions for alternate paths
134 if (isEntityProxy == false) {
135 List<String> uriPaths = sbinding.getUriPath();
136 for (String uriPath : uriPaths) {
137 perm = buildAdminPermission(tbinding.getId(),
138 uriPath.toLowerCase());
147 private Permission buildAdminPermission(String tenantId, String resourceName) {
148 String description = "Generated admin permission.";
149 return AuthorizationCommon.createPermission(tenantId, resourceName, description, AuthorizationCommon.ACTIONGROUP_CRUDL_NAME);
153 * createDefaultReaderPermissions creates read only permissions for all services
154 * used by the given tenant
158 public List<Permission> createDefaultReaderPermissions(String tenantId, boolean isEntityProxy) {
159 ArrayList<Permission> apcList = new ArrayList<Permission>();
160 TenantBindingType tbinding = tenantBindings.get(tenantId);
161 for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
162 //add permissions for the main path
163 String resourceName = sbinding.getName().toLowerCase().trim();
164 if (isEntityProxy == true) {
165 resourceName = SecurityUtils.getResourceEntity(resourceName);
167 Permission perm = buildReaderPermission(tbinding.getId(),
171 //add permissions for alternate paths
172 if (isEntityProxy == false) {
173 List<String> uriPaths = sbinding.getUriPath();
174 for (String uriPath : uriPaths) {
175 perm = buildReaderPermission(tbinding.getId(),
176 uriPath.toLowerCase());
185 private Permission buildReaderPermission(String tenantId, String resourceName) {
186 String description = "Generated read-only permission.";
187 return AuthorizationCommon.createPermission(tenantId, resourceName, description, AuthorizationCommon.ACTIONGROUP_RL_NAME);
190 public List<Permission> getDefaultPermissions() {
191 if (allPermList == null) {
192 allPermList = new ArrayList<Permission>();
193 allPermList.addAll(adminPermList);
194 allPermList.addAll(readerPermList);
199 public List<Permission> getDefaultAdminPermissions() {
200 return adminPermList;
203 public List<Permission> getDefaultReaderPermissions() {
204 return readerPermList;
208 * createDefaultRoles creates default admin and reader roles
209 * for each tenant found in the given tenant binding file
211 public void createDefaultRoles() {
212 for (String tenantId : tenantBindings.keySet()) {
214 Role arole = buildTenantAdminRole(tenantId);
215 adminRoles.add(arole);
217 Role rrole = buildTenantReaderRole(tenantId);
218 readerRoles.add(rrole);
222 private Role buildTenantAdminRole(String tenantId) {
223 String type = "admin";
224 Role result = AuthorizationCommon.getRole(tenantId, AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR);
226 if (result == null) {
227 // the role doesn't exist already, so we need to create it
228 String description = "Generated tenant " + type + " role.";
229 result = AuthorizationCommon.createRole(tenantId, AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR, description);
235 private Role buildTenantReaderRole(String tenantId) {
236 String type = "read only";
237 Role result = AuthorizationCommon.getRole(tenantId, AuthorizationCommon.ROLE_TENANT_READER);
239 if (result == null) {
240 // the role doesn't exist already, so we need to create it
241 String description = "Generated tenant " + type + " role.";
242 result = AuthorizationCommon.createRole(tenantId, AuthorizationCommon.ROLE_TENANT_READER, description);
249 public List<Role> getDefaultRoles() {
250 if (allRoleList == null) {
251 allRoleList = new ArrayList<Role>();
252 allRoleList.addAll(adminRoles);
253 allRoleList.addAll(readerRoles);
254 // Finally, add the "super" role to the list
255 allRoleList.add(cspaceAdminRole);
260 public void associateDefaultPermissionsRoles() {
261 for (Permission p : adminPermList) {
262 PermissionRole permAdmRole = associatePermissionRoles(p, adminRoles, true);
263 adminPermRoleList.add(permAdmRole);
266 for (Permission p : readerPermList) {
267 PermissionRole permRdrRole = associatePermissionRoles(p, readerRoles, true);
268 readerPermRoleList.add(permRdrRole);
271 //CSpace Administrator has all access
272 List<Role> roles = new ArrayList<Role>();
273 roles.add(cspaceAdminRole);
274 for (Permission p : adminPermList) {
275 PermissionRole permCAdmRole = associatePermissionRoles(p, roles, false);
276 adminPermRoleList.add(permCAdmRole);
280 public List<PermissionRole> associatePermissionsRoles(List<Permission> perms, List<Role> roles, boolean enforceTenancy) {
281 List<PermissionRole> result = null;
283 List<PermissionRole> permRoles = new ArrayList<PermissionRole>();
284 for (Permission perm : perms) {
285 PermissionRole permRole = associatePermissionRoles(perm, roles, enforceTenancy);
286 if (permRole != null) {
287 permRoles.add(permRole);
291 if (permRoles.isEmpty() == false) {
298 private PermissionRole associatePermissionRoles(Permission perm,
299 List<Role> roles, boolean enforceTenancy) {
300 PermissionRole result = null;
302 PermissionRole pr = new PermissionRole();
303 pr.setSubject(SubjectType.ROLE);
304 List<PermissionValue> permValues = new ArrayList<PermissionValue>();
305 pr.setPermission(permValues);
306 PermissionValue permValue = new PermissionValue();
307 permValue.setPermissionId(perm.getCsid());
308 permValue.setResourceName(perm.getResourceName().toLowerCase());
309 permValue.setActionGroup(perm.getActionGroup());
310 permValues.add(permValue);
312 List<RoleValue> roleValues = new ArrayList<RoleValue>();
313 for (Role role : roles) {
314 boolean tenantIdsMatched = true;
315 if (enforceTenancy == true) {
316 tenantIdsMatched = role.getTenantId().equals(perm.getTenantId());
318 if (tenantIdsMatched == true) {
319 RoleValue rv = new RoleValue();
320 // This needs to use the qualified name, not the display name
321 rv.setRoleName(role.getRoleName().toUpperCase());
322 rv.setRoleId(role.getCsid());
325 if (logger.isTraceEnabled() == true) {
326 logger.trace("Role and Permission tenant ID did not match."); //FIXME: REM - Remove this debug statement.
331 // If 'roleValues' is not empty, then associate it with the incoming 'perm' values
332 // otherwise, return null;
334 if (roleValues.isEmpty() == false) {
335 pr.setRole(roleValues);
342 public List<PermissionRole> getDefaultPermissionRoles() {
343 if (allPermRoleList == null) {
344 allPermRoleList = new ArrayList<PermissionRole>();
345 allPermRoleList.addAll(adminPermRoleList);
346 allPermRoleList.addAll(readerPermRoleList);
348 return allPermRoleList;
351 public List<PermissionRole> getDefaultAdminPermissionRoles() {
352 return adminPermRoleList;
355 public List<PermissionRole> getDefaultReaderPermissionRoles() {
356 return readerPermRoleList;
359 private Role buildCSpaceAdminRole() {
360 Role role = new Role();
362 role.setDescription("A generated super role that has permissions across tenancies.");
363 role.setDisplayName(AuthorizationCommon.ROLE_ADMINISTRATOR);
364 role.setRoleName(AuthorizationCommon.getQualifiedRoleName(
365 AuthorizationCommon.ADMINISTRATOR_TENANT_ID, role.getDisplayName()));
366 role.setCsid(AuthorizationCommon.ROLE_ADMINISTRATOR_ID);
367 role.setTenantId(AuthorizationCommon.ADMINISTRATOR_TENANT_ID);
372 public void exportDefaultRoles(String fileName) {
373 RolesList rList = new RolesList();
374 rList.setRole(this.getDefaultRoles());
376 // Since it is missing the @XMLRootElement annotation, create a JAXBElement wrapper for the RoleList instance
377 // so we can have it marshalled it correctly.
379 org.collectionspace.services.authorization.ObjectFactory objectFactory = new org.collectionspace.services.authorization.ObjectFactory();
380 toFile(objectFactory.createRolesList(rList), RolesList.class,
382 if (logger.isDebugEnabled()) {
383 logger.debug("exported roles to " + fileName);
387 public void exportDefaultPermissions(String fileName) {
388 PermissionsList pcList = new PermissionsList();
389 pcList.setPermission(this.getDefaultPermissions());
390 org.collectionspace.services.authorization.ObjectFactory objectFactory =
391 new org.collectionspace.services.authorization.ObjectFactory();
392 toFile(pcList, PermissionsList.class,
393 // toFile(objectFactory.createPermissionsList(pcList), PermissionsList.class,
395 if (logger.isDebugEnabled()) {
396 logger.debug("exported permissions to " + fileName);
400 public void exportDefaultPermissionRoles(String fileName) {
401 PermissionsRolesList psrsl = new PermissionsRolesList();
402 psrsl.setPermissionRole(this.getDefaultAdminPermissionRoles());
403 toFile(psrsl, PermissionsRolesList.class,
405 if (logger.isDebugEnabled()) {
406 logger.debug("exported permissions-roles to " + fileName);
410 private void toFile(Object o, Class jaxbClass, String fileName) {
411 File f = new File(fileName);
413 JAXBContext jc = JAXBContext.newInstance(jaxbClass);
414 Marshaller m = jc.createMarshaller();
415 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
418 } catch (Exception e) {