import org.collectionspace.services.authorization.RoleValue;
import org.collectionspace.services.authorization.RolesList;
import org.collectionspace.services.authorization.SubjectType;
+import org.collectionspace.services.common.authorization_mgt.AuthorizationCommon;
import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
import org.collectionspace.services.common.service.ServiceBindingType;
import org.collectionspace.services.common.tenant.TenantBindingType;
*/
public class AuthorizationGen {
- final public static String ROLE_PREFIX = "ROLE_";
- final public static String ROLE_ADMINISTRATOR = "ADMINISTRATOR";
- final public static String ROLE_TENANT_ADMINISTRATOR = "TENANT_ADMINISTRATOR";
- final public static String ROLE_TENANT_READER = "TENANT_READER";
- final public static String ROLE_ADMINISTRATOR_ID = "0";
- final public static String ADMINISTRATOR_TENANT_ID = "0";
- //
- // ActionGroup labels/constants
- //
- final public static String ACTIONGROUP_CRUDL = "CRUDL";
- final public static String ACTIONGROUP_RL = "RL";
//
// Should the base resource act as a proxy for its sub-resources for AuthZ purposes
//
}
private Permission buildAdminPermission(String tenantId, String resourceName) {
- String id = UUID.randomUUID().toString(); //FIXME: Could this be something like a refname instead of a UUID?
- Permission perm = new Permission();
- perm.setCsid(id);
- perm.setDescription("generated admin permission");
- perm.setCreatedAtItem(new Date());
- perm.setResourceName(resourceName.toLowerCase().trim());
- perm.setEffect(EffectType.PERMIT);
- perm.setTenantId(tenantId);
-
- perm.setActionGroup(ACTIONGROUP_CRUDL);
- ArrayList<PermissionAction> pas = new ArrayList<PermissionAction>();
- perm.setAction(pas);
-
- PermissionAction permAction = PermissionActionUtil.create(perm, ActionType.CREATE);
- pas.add(permAction);
-
- permAction = PermissionActionUtil.create(perm, ActionType.READ);
- pas.add(permAction);
-
- permAction = PermissionActionUtil.create(perm, ActionType.UPDATE);
- pas.add(permAction);
-
- permAction = PermissionActionUtil.create(perm, ActionType.DELETE);
- pas.add(permAction);
-
- permAction = PermissionActionUtil.create(perm, ActionType.SEARCH);
- pas.add(permAction);
-
- return perm;
+ String description = "Generated admin permission.";
+ return AuthorizationCommon.createPermission(tenantId, resourceName, description, AuthorizationCommon.ACTIONGROUP_CRUDL_NAME);
}
/**
}
private Permission buildReaderPermission(String tenantId, String resourceName) {
- String id = UUID.randomUUID().toString();
- Permission perm = new Permission();
- perm.setCsid(id);
- perm.setCreatedAtItem(new Date());
- perm.setDescription("generated readonly permission");
- perm.setResourceName(resourceName.toLowerCase().trim());
- perm.setEffect(EffectType.PERMIT);
- perm.setTenantId(tenantId);
-
- perm.setActionGroup(ACTIONGROUP_RL);
- ArrayList<PermissionAction> pas = new ArrayList<PermissionAction>();
- perm.setAction(pas);
-
- PermissionAction permAction = PermissionActionUtil.create(perm, ActionType.READ);
- pas.add(permAction);
-
- permAction = PermissionActionUtil.create(perm, ActionType.SEARCH);
- pas.add(permAction);
-
- return perm;
+ String description = "Generated read-only permission.";
+ return AuthorizationCommon.createPermission(tenantId, resourceName, description, AuthorizationCommon.ACTIONGROUP_CRUDL_NAME);
}
public List<Permission> getDefaultPermissions() {
}
private Role buildTenantAdminRole(String tenantId) {
- return buildTenantRole(tenantId, ROLE_TENANT_ADMINISTRATOR, "admin");
+ String type = "admin";
+ Role result = AuthorizationCommon.getRole(tenantId, AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR);
+
+ if (result == null) {
+ // the role doesn't exist already, so we need to create it
+ String description = "Generated tenant " + type + " role.";
+ result = AuthorizationCommon.createRole(tenantId, AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR, description);
+ }
+
+ return result;
}
private Role buildTenantReaderRole(String tenantId) {
- return buildTenantRole(tenantId, ROLE_TENANT_READER, "read only");
- }
-
- private Role buildTenantRole(String tenantId, String name, String type) {
- Role role = null;
-
- String roleName = ROLE_PREFIX + tenantId + "_" + name;
- role = AuthorizationStore.getRoleByName(roleName, tenantId);
- if (role == null) {
+ String type = "read only";
+ Role result = AuthorizationCommon.getRole(tenantId, AuthorizationCommon.ROLE_TENANT_READER);
+
+ if (result == null) {
// the role doesn't exist already, so we need to create it
- role = new Role();
- role.setCreatedAtItem(new Date());
- role.setDisplayName(name);
- role.setRoleName(roleName);
- String id = UUID.randomUUID().toString();
- role.setCsid(id);
- role.setDescription("generated tenant " + type + " role");
- role.setTenantId(tenantId);
- role.setMetadataProtection(RoleClient.IMMUTABLE);
- role.setPermsProtection(RoleClient.IMMUTABLE);
- }
+ String description = "Generated tenant " + type + " role.";
+ result = AuthorizationCommon.createRole(tenantId, AuthorizationCommon.ROLE_TENANT_READER, description);
+ }
- return role;
+ return result;
}
+
public List<Role> getDefaultRoles() {
if (allRoleList == null) {
private Role buildCSpaceAdminRole() {
Role role = new Role();
- role.setDisplayName(ROLE_ADMINISTRATOR);
- role.setRoleName(ROLE_PREFIX + role.getDisplayName());
- role.setCsid(ROLE_ADMINISTRATOR_ID);
- role.setTenantId(ADMINISTRATOR_TENANT_ID);
+ role.setDisplayName(AuthorizationCommon.ROLE_ADMINISTRATOR);
+ role.setRoleName(AuthorizationCommon.ROLE_PREFIX + role.getDisplayName());
+ role.setCsid(AuthorizationCommon.ROLE_ADMINISTRATOR_ID);
+ role.setTenantId(AuthorizationCommon.ADMINISTRATOR_TENANT_ID);
return role;
}
import java.sql.SQLException;\r
import java.sql.Statement;\r
import java.util.ArrayList;\r
+import java.util.Date;\r
import java.util.Hashtable;\r
import java.util.List;\r
import java.util.UUID;\r
\r
import org.collectionspace.services.authorization.AuthZ;\r
import org.collectionspace.services.authorization.CSpaceAction;\r
+import org.collectionspace.services.authorization.PermissionActionUtil;\r
import org.collectionspace.services.authorization.PermissionException;\r
import org.collectionspace.services.authorization.PermissionRole;\r
+import org.collectionspace.services.authorization.PermissionValue;\r
+import org.collectionspace.services.authorization.Role;\r
import org.collectionspace.services.authorization.RoleValue;\r
+import org.collectionspace.services.authorization.SubjectType;\r
import org.collectionspace.services.authorization.URIResourceImpl;\r
+import org.collectionspace.services.authorization.perms.ActionType;\r
import org.collectionspace.services.authorization.perms.EffectType;\r
import org.collectionspace.services.authorization.perms.Permission;\r
import org.collectionspace.services.authorization.perms.PermissionAction;\r
+\r
+import org.collectionspace.services.client.RoleClient;\r
+import org.collectionspace.services.client.workflow.WorkflowClient;\r
+\r
+import org.collectionspace.services.common.authorization_mgt.AuthorizationStore;\r
import org.collectionspace.services.common.config.ServiceConfigUtils;\r
import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;\r
import org.collectionspace.services.common.document.DocumentHandler;\r
import org.collectionspace.services.common.storage.DatabaseProductType;\r
import org.collectionspace.services.common.storage.JDBCTools;\r
import org.collectionspace.services.common.tenant.TenantBindingType;\r
+\r
import org.collectionspace.services.lifecycle.Lifecycle;\r
-import org.mortbay.log.Log;\r
+import org.collectionspace.services.lifecycle.TransitionDef;\r
+import org.collectionspace.services.lifecycle.TransitionDefList;\r
+\r
+//import org.mortbay.log.Log;\r
import org.slf4j.Logger;\r
import org.slf4j.LoggerFactory;\r
+\r
import org.springframework.security.acls.model.AlreadyExistsException;\r
\r
\r
public class AuthorizationCommon {\r
+ \r
+ //\r
+ // ActionGroup labels/constants\r
+ //\r
+ \r
+ // for READ-WRITE\r
+ final public static String ACTIONGROUP_CRUDL_NAME = "CRUDL";\r
+ final public static ActionType[] ACTIONSET_CRUDL = {ActionType.CREATE, ActionType.READ, ActionType.UPDATE, ActionType.DELETE, ActionType.SEARCH};\r
+ // for READ-ONLY\r
+ final public static String ACTIONGROUP_RL_NAME = "RL";\r
+ final public static ActionType[] ACTIONSET_RL = {ActionType.READ, ActionType.SEARCH};\r
+ \r
+ /*\r
+ * Inner class to deal with predefined ADMIN and READER action groupds\r
+ */\r
+ public class ActionGroup {\r
+ String name;\r
+ ActionType[] actions;\r
+ }\r
+ \r
+ static ActionGroup ACTIONGROUP_CRUDL;\r
+ static ActionGroup ACTIONGROUP_RL;\r
+ \r
+ // A static block to initialize the predefined action groups\r
+ static {\r
+ AuthorizationCommon ac = new AuthorizationCommon();\r
+ // For admin\r
+ ACTIONGROUP_CRUDL = ac.new ActionGroup();\r
+ ACTIONGROUP_CRUDL.name = ACTIONGROUP_CRUDL_NAME;\r
+ ACTIONGROUP_CRUDL.actions = ACTIONSET_CRUDL;\r
+ // For reader\r
+ ACTIONGROUP_RL = ac.new ActionGroup();\r
+ ACTIONGROUP_RL.name = ACTIONGROUP_RL_NAME;\r
+ ACTIONGROUP_RL.actions = ACTIONSET_RL;\r
+\r
+ }\r
+ \r
final static Logger logger = LoggerFactory.getLogger(AuthorizationCommon.class);\r
\r
+ final public static String ROLE_ADMINISTRATOR = "ADMINISTRATOR";\r
+ final public static String ROLE_TENANT_ADMINISTRATOR = "TENANT_ADMINISTRATOR";\r
+ final public static String ROLE_TENANT_READER = "TENANT_READER";\r
+ final public static String ROLE_ADMINISTRATOR_ID = "0";\r
+ final public static String ADMINISTRATOR_TENANT_ID = "0";\r
+ \r
public static final String TENANT_ADMIN_ACCT_PREFIX = "admin@"; \r
public static final String TENANT_READER_ACCT_PREFIX = "reader@"; \r
public static final String ROLE_PREFIX = "ROLE_"; \r
public static String ROLE_SPRING_ADMIN_ID = "-1";\r
public static String ROLE_SPRING_ADMIN_NAME = "ROLE_SPRING_ADMIN";\r
\r
+ public static Role getRole(String tenantId, String displayName) {\r
+ Role role = null;\r
+ \r
+ String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, displayName);\r
+ role = AuthorizationStore.getRoleByName(roleName, tenantId);\r
+ \r
+ return role;\r
+ }\r
+ \r
+ public static Role createRole(String tenantId, String name, String description) {\r
+ return createRole(tenantId, name, description, false /* mutable by default */);\r
+ }\r
+ \r
+ public static Role createRole(String tenantId, String name, String description, boolean immutable) {\r
+ Role role = new Role();\r
+ \r
+ role.setCreatedAtItem(new Date());\r
+ role.setDisplayName(name);\r
+ String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, name); \r
+ role.setRoleName(roleName);\r
+ String id = UUID.randomUUID().toString(); //FIXME: The qualified role name should be unique enough to use as an ID/key\r
+ role.setCsid(id);\r
+ role.setDescription(description);\r
+ role.setTenantId(tenantId);\r
+ if (immutable == true) {\r
+ role.setMetadataProtection(RoleClient.IMMUTABLE);\r
+ role.setPermsProtection(RoleClient.IMMUTABLE);\r
+ }\r
+ \r
+ return role;\r
+ }\r
+ \r
/**\r
- * addPermissionsForUri add permissions from given permission configuration\r
+ * Add permission to the Spring Security tables\r
* with assumption that resource is of type URI\r
* @param permission configuration\r
*/\r
public static void addPermissionsForUri(Permission perm,\r
PermissionRole permRole) throws PermissionException {\r
- List<String> principals = new ArrayList<String>();\r
+ //\r
+ // First check the integrity of the incoming arguments.\r
+ //\r
if (!perm.getCsid().equals(permRole.getPermission().get(0).getPermissionId())) {\r
throw new IllegalArgumentException("permission ids do not"\r
+ " match for role=" + permRole.getRole().get(0).getRoleName()\r
+ " with permissionId=" + permRole.getPermission().get(0).getPermissionId()\r
+ " for permission with csid=" + perm.getCsid());\r
}\r
+ \r
+ List<String> principals = new ArrayList<String>(); \r
for (RoleValue roleValue : permRole.getRole()) {\r
principals.add(roleValue.getRoleName());\r
}\r
return JDBCTools.getConnection(JDBCTools.CSPACE_REPOSITORY_NAME);\r
}\r
\r
+ /*\r
+ * Spring security seems to require that all of our role names start\r
+ * with the ROLE_PREFIX string.\r
+ */\r
+ public static String getQualifiedRoleName(String tenantId, String name) {\r
+ String result = name;\r
+ \r
+ String qualifiedName = ROLE_PREFIX + tenantId.toUpperCase() + "_" + name.toUpperCase(); \r
+ if (name.equals(qualifiedName) == false) {\r
+ result = qualifiedName;\r
+ }\r
+ \r
+ return result;\r
+ }\r
+ \r
+ private static ActionGroup getActionGroup(String actionGroupStr) {\r
+ ActionGroup result = null;\r
+ \r
+ if (actionGroupStr.equalsIgnoreCase(ACTIONGROUP_CRUDL_NAME)) {\r
+ result = ACTIONGROUP_CRUDL;\r
+ } else if (actionGroupStr.equalsIgnoreCase(ACTIONGROUP_RL_NAME)) {\r
+ result = ACTIONGROUP_RL;\r
+ }\r
+ \r
+ return result;\r
+ }\r
+ \r
+ public static Permission createPermission(String tenantId,\r
+ String resourceName,\r
+ String description,\r
+ String actionGroupStr) {\r
+ Permission result = null;\r
+ \r
+ ActionGroup actionGroup = getActionGroup(actionGroupStr);\r
+ result = createPermission(tenantId, resourceName, description, actionGroup);\r
+ \r
+ return result;\r
+ }\r
+ \r
+ private static Permission createPermission(String tenantId,\r
+ String resourceName,\r
+ String description,\r
+ ActionGroup actionGroup) {\r
+ String id = UUID.randomUUID().toString(); //FIXME: Could this be something like a refname instead of a UUID?\r
+ Permission perm = new Permission();\r
+ perm.setCsid(id);\r
+ perm.setDescription(description);\r
+ perm.setCreatedAtItem(new Date());\r
+ perm.setResourceName(resourceName.toLowerCase().trim());\r
+ perm.setEffect(EffectType.PERMIT);\r
+ perm.setTenantId(tenantId);\r
+ \r
+ perm.setActionGroup(actionGroup.name);\r
+ ArrayList<PermissionAction> pas = new ArrayList<PermissionAction>();\r
+ perm.setAction(pas);\r
+ for (ActionType actionType : actionGroup.actions) {\r
+ PermissionAction permAction = createPermissionAction(perm, actionType);\r
+ pas.add(permAction);\r
+ }\r
+ \r
+ return perm;\r
+ }\r
+ \r
+ private static Permission createWorkflowPermission(TenantBindingType tenantBinding,\r
+ ServiceBindingType serviceBinding,\r
+ TransitionDef transitionDef,\r
+ ActionGroup actionGroup)\r
+ {\r
+ Permission result = null;\r
+ \r
+ String tenantId = tenantBinding.getId();\r
+ String resourceName = serviceBinding.getName().toLowerCase().trim()\r
+ + WorkflowClient.SERVICE_AUTHZ_SUFFIX\r
+ + transitionDef.getName();\r
+ String description = "A generate workflow permission for actiongroup " + actionGroup.name;\r
+ result = createPermission(tenantId, resourceName, description, actionGroup);\r
+ \r
+ return result;\r
+ }\r
+ \r
+ private static PermissionRole createPermissionRole(Permission permission,\r
+ Role role,\r
+ boolean enforceTenancy) throws Exception\r
+ {\r
+ PermissionRole permRole = new PermissionRole();\r
+ \r
+ if (enforceTenancy && role.getTenantId().equalsIgnoreCase(permission.getTenantId())) {\r
+ permRole.setSubject(SubjectType.ROLE);\r
+ //\r
+ // Set of the permission value list of the permrole\r
+ //\r
+ List<PermissionValue> permValues = new ArrayList<PermissionValue>();\r
+ PermissionValue permValue = new PermissionValue();\r
+ permValue.setPermissionId(permission.getCsid());\r
+ permValue.setResourceName(permission.getResourceName().toLowerCase());\r
+ permValue.setActionGroup(permission.getActionGroup());\r
+ permValues.add(permValue);\r
+ permRole.setPermission(permValues);\r
+ //\r
+ // Set of the role value list of the permrole\r
+ //\r
+ List<RoleValue> roleValues = new ArrayList<RoleValue>();\r
+ RoleValue rv = new RoleValue();\r
+ // This needs to use the qualified name, not the display name\r
+ rv.setRoleName(role.getRoleName());\r
+ rv.setRoleId(role.getCsid());\r
+ roleValues.add(rv);\r
+ permRole.setRole(roleValues);\r
+ } else {\r
+ String errMsg = "The tenant ID of the role: " + role.getTenantId()\r
+ + " did not match the tenant ID of the permission: " + permission.getTenantId();\r
+ throw new Exception(errMsg);\r
+ }\r
+ \r
+ return permRole;\r
+ }\r
+ \r
public static void createDefaultPermissions(TenantBindingConfigReaderImpl tenantBindingConfigReader) throws Exception\r
{\r
+ PermissionAction pa = new PermissionAction();\r
+ pa.getHjid();\r
+\r
Hashtable<String, TenantBindingType> tenantBindings =\r
tenantBindingConfigReader.getTenantBindings();\r
for (String tenantId : tenantBindings.keySet()) {\r
DocumentHandler docHandler = ServiceConfigUtils.createDocumentHandlerInstance(\r
tenantBinding, serviceBinding);\r
Lifecycle lifecycle = docHandler.getLifecycle();\r
+ TransitionDefList transitionDefList = lifecycle.getTransitionDefList();\r
+ for (TransitionDef transitionDef : transitionDefList.getTransitionDef()) {\r
+ //\r
+ // Create the permission for the admin role\r
+ //\r
+ Permission adminPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, AuthorizationCommon.ACTIONGROUP_CRUDL);\r
+ Role adminRole = AuthorizationCommon.getRole(tenantBinding.getId(), AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR);\r
+ PermissionRole adminPermRole = createPermissionRole(adminPerm, adminRole, true);\r
+ addPermissionsForUri(adminPerm, adminPermRole);\r
+ //\r
+ // Create the permission for the read-only role\r
+ Permission readonlyPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, AuthorizationCommon.ACTIONGROUP_RL);\r
+ Role readonlyRole = AuthorizationCommon.getRole(tenantBinding.getId(), AuthorizationCommon.ROLE_TENANT_READER);\r
+ PermissionRole readonlyPermRole = createPermissionRole(readonlyPerm, readonlyRole, true);\r
+ addPermissionsForUri(readonlyPerm, readonlyPermRole);\r
+ //\r
+ // Create the permission for the super-admin role. Note we use the same "adminPerm" instance we used for the "adminPermRole" instance\r
+ //\r
+ Role superRole = AuthorizationCommon.getRole(tenantBinding.getId(), AuthorizationCommon.ROLE_TENANT_READER);\r
+ PermissionRole superPermRole = createPermissionRole(adminPerm, superRole, false);\r
+ addPermissionsForUri(adminPerm, superPermRole);\r
+ }\r
} catch (IllegalStateException e) {\r
- Log.debug(e.getLocalizedMessage(), e); //We end up here if there is no document handler for the service -this is ok for some of the services.\r
+ logger.debug(e.getLocalizedMessage(), e); //We end up here if there is no document handler for the service -this is ok for some of the services.\r
}\r
}\r
}\r
- // For each service binding in each tenancy, get the Nuxeo document type and retrieve it's life cycle type. For\r
- // that life cycle type, ask Nuxeo for all the configured transitions. For each of those transitions,\r
- // create:\r
- // * a URI of the form - /<service>/*/workflow/<transition>\r
- // * a CRUDL Permission for the URI\r
- // * a RL Permission for the URI\r
- // * a PermissionRole for admin role\r
- // * a PermissionRole for the reader role\r
- // \r
- // * add a new Permission/PermissionRole tuple to the Spring AuthZ tables\r
- // * persist the new Permission, and PermissionRole to the cspace database\r
- \r
}\r
\r
/*\r
private static String getDefaultReaderUserID(String tenantName) {\r
return TENANT_READER_ACCT_PREFIX+tenantName;\r
}\r
+ \r
+ static public PermissionAction createPermissionAction(Permission perm,\r
+ ActionType actionType) {\r
+ PermissionAction pa = new PermissionAction();\r
+\r
+ CSpaceAction action = URIResourceImpl.getAction(actionType);\r
+ URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),\r
+ perm.getResourceName(), action);\r
+ pa.setName(actionType);\r
+ pa.setObjectIdentity(uriRes.getHashedId().toString());\r
+ pa.setObjectIdentityResource(uriRes.getId());\r
+ \r
+ return pa;\r
+ }\r
+\r
+ static public PermissionAction update(Permission perm, PermissionAction permAction) {\r
+ PermissionAction pa = new PermissionAction();\r
+\r
+ CSpaceAction action = URIResourceImpl.getAction(permAction.getName());\r
+ URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),\r
+ perm.getResourceName(), action);\r
+ pa.setObjectIdentity(uriRes.getHashedId().toString());\r
+ pa.setObjectIdentityResource(uriRes.getId());\r
+ \r
+ return pa;\r
+ }\r
+ \r
+ \r
+\r
}\r