/* * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.wso2.carbon.identity.application.mgt; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.RegistryType; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; import org.wso2.carbon.identity.application.common.model.ApplicationPermission; import org.wso2.carbon.identity.application.common.model.InboundAuthenticationRequestConfig; import org.wso2.carbon.identity.application.common.model.PermissionsAndRoleConfig; import org.wso2.carbon.identity.application.common.model.Property; import org.wso2.carbon.identity.application.common.model.ServiceProvider; import org.wso2.carbon.identity.application.mgt.dao.ApplicationDAO; import org.wso2.carbon.registry.api.Collection; import org.wso2.carbon.registry.api.Registry; import org.wso2.carbon.registry.api.RegistryException; import org.wso2.carbon.registry.api.Resource; import org.wso2.carbon.registry.core.RegistryConstants; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.UserCoreConstants; import org.wso2.carbon.user.core.UserRealm; import org.wso2.carbon.user.core.util.UserCoreUtil; import org.wso2.carbon.user.mgt.UserMgtConstants; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class ApplicationMgtUtil { public static final String APPLICATION_ROOT_PERMISSION = "applications"; public static final String PATH_CONSTANT = RegistryConstants.PATH_SEPARATOR; private static final List<String> paths = new ArrayList<String>(); private static String applicationNode; private static Log log = LogFactory.getLog(ApplicationMgtUtil.class); private ApplicationMgtUtil() { } public static org.wso2.carbon.user.api.Permission[] buildPermissions(String applicationName, String[] permissions) { org.wso2.carbon.user.api.Permission[] permissionSet = null; if (permissions != null) { permissionSet = new org.wso2.carbon.user.api.Permission[permissions.length]; int i = 0; for (String permissionString : permissions) { permissionSet[i] = new org.wso2.carbon.user.api.Permission(applicationName + "\\" + permissionString, "ui.execute"); } } return permissionSet; } public static boolean isUserAuthorized(String applicationName, String username, int applicationID) throws IdentityApplicationManagementException { if (!isUserAuthorized(applicationName, username)) { // maybe the role name of the app has updated. In this case, lets // load back the old app name ApplicationDAO appDAO = ApplicationMgtSystemConfig.getInstance().getApplicationDAO(); String storedApplicationName = appDAO.getApplicationName(applicationID); return isUserAuthorized(storedApplicationName, username); } return true; } /** * @param applicationName * @param username * @return * @throws IdentityApplicationManagementException */ public static boolean isUserAuthorized(String applicationName, String username) throws IdentityApplicationManagementException { String applicationRoleName = getAppRoleName(applicationName); try { if (log.isDebugEnabled()) { log.debug("Checking whether user has role : " + applicationRoleName + " by retrieving role list of " + "user : " + username); } String[] userRoles = CarbonContext.getThreadLocalCarbonContext().getUserRealm() .getUserStoreManager().getRoleListOfUser(username); for (String userRole : userRoles) { if (applicationRoleName.equals(userRole)) { return true; } } } catch (UserStoreException e) { throw new IdentityApplicationManagementException("Error while checking authorization for user: " + username + " for application: " + applicationName, e); } return false; } /** * Create a role for the application and assign the user to that role. * * @param applicationName * @throws IdentityApplicationManagementException */ public static void createAppRole(String applicationName, String username) throws IdentityApplicationManagementException { String roleName = getAppRoleName(applicationName); String[] usernames = {username}; try { // create a role for the application and assign the user to that role. if (log.isDebugEnabled()) { log.debug("Creating application role : " + roleName + " and assign the user : " + Arrays.toString(usernames) + " to that role"); } CarbonContext.getThreadLocalCarbonContext().getUserRealm().getUserStoreManager() .addRole(roleName, usernames, null); } catch (UserStoreException e) { throw new IdentityApplicationManagementException("Error while creating application role: " + roleName + " with user " + username, e); } } private static String getAppRoleName(String applicationName) { return ApplicationConstants.APPLICATION_DOMAIN + UserCoreConstants.DOMAIN_SEPARATOR + applicationName; } /** * Delete the role of the app * * @param applicationName * @throws IdentityApplicationManagementException */ public static void deleteAppRole(String applicationName) throws IdentityApplicationManagementException { String roleName = getAppRoleName(applicationName); try { if (log.isDebugEnabled()) { log.debug("Deleting application role : " + roleName); } CarbonContext.getThreadLocalCarbonContext().getUserRealm().getUserStoreManager() .deleteRole(roleName); } catch (UserStoreException e) { throw new IdentityApplicationManagementException("Error while creating application", e); } } /** * @param oldName * @param newName * @throws IdentityApplicationManagementException */ public static void renameRole(String oldName, String newName) throws UserStoreException { if (log.isDebugEnabled()) { log.debug("Renaming application role : " + UserCoreUtil.addInternalDomainName(oldName) + " to new role : " + UserCoreUtil.addInternalDomainName(newName)); } CarbonContext.getThreadLocalCarbonContext().getUserRealm().getUserStoreManager() .updateRoleName(UserCoreUtil.addInternalDomainName(oldName), UserCoreUtil.addInternalDomainName(newName)); } /** * Rename the registry path node name for a deleted Service provider role. * * @param oldName * @param newName * @throws IdentityApplicationManagementException */ public static void renameAppPermissionPathNode(String oldName, String newName) throws IdentityApplicationManagementException { List<ApplicationPermission> loadPermissions = loadPermissions(oldName); String newApplicationNode = ApplicationMgtUtil.getApplicationPermissionPath() + PATH_CONSTANT + oldName; Registry tenantGovReg = CarbonContext.getThreadLocalCarbonContext().getRegistry( RegistryType.USER_GOVERNANCE); //creating new application node try { for (ApplicationPermission applicationPermission : loadPermissions) { tenantGovReg.delete(newApplicationNode + PATH_CONSTANT + applicationPermission.getValue()); } tenantGovReg.delete(newApplicationNode); Collection permissionNode = tenantGovReg.newCollection(); permissionNode.setProperty("name", newName); newApplicationNode = ApplicationMgtUtil.getApplicationPermissionPath() + PATH_CONSTANT + newName; ApplicationMgtUtil.applicationNode = newApplicationNode; tenantGovReg.put(newApplicationNode, permissionNode); addPermission(loadPermissions.toArray(new ApplicationPermission[loadPermissions.size()]), tenantGovReg); } catch (RegistryException e) { throw new IdentityApplicationManagementException("Error while renaming permission node " + oldName + "to " + newName, e); } } /** * @param applicationName * @param permissionsConfig * @throws IdentityApplicationManagementException */ public static void storePermissions(String applicationName, String username, PermissionsAndRoleConfig permissionsConfig) throws IdentityApplicationManagementException { Registry tenantGovReg = CarbonContext.getThreadLocalCarbonContext().getRegistry( RegistryType.USER_GOVERNANCE); String permissionResourcePath = getApplicationPermissionPath(); try { if (!tenantGovReg.resourceExists(permissionResourcePath)) { boolean loggedInUserChanged = false; UserRealm realm = (UserRealm) CarbonContext.getThreadLocalCarbonContext().getUserRealm(); if (!realm.getAuthorizationManager() .isUserAuthorized(username, permissionResourcePath, UserMgtConstants.EXECUTE_ACTION)) { //Logged in user is not authorized to create the permission. // Temporarily change the user to the admin for creating the permission PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername( realm.getRealmConfiguration().getAdminUserName()); tenantGovReg = CarbonContext.getThreadLocalCarbonContext() .getRegistry(RegistryType.USER_GOVERNANCE); loggedInUserChanged = true; } Collection appRootNode = tenantGovReg.newCollection(); appRootNode.setProperty("name", "Applications"); tenantGovReg.put(permissionResourcePath, appRootNode); if (loggedInUserChanged) { PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username); } } if (permissionsConfig != null) { ApplicationPermission[] permissions = permissionsConfig.getPermissions(); if (permissions == null || permissions.length < 1) { return; } // creating the application node in the tree String appNode = permissionResourcePath + PATH_CONSTANT + applicationName; Collection appNodeColl = tenantGovReg.newCollection(); tenantGovReg.put(appNode, appNodeColl); // now start storing the permissions for (ApplicationPermission permission : permissions) { String permissinPath = appNode + PATH_CONSTANT + permission; Resource permissionNode = tenantGovReg.newResource(); permissionNode.setProperty("name", permission.getValue()); tenantGovReg.put(permissinPath, permissionNode); } } } catch (Exception e) { throw new IdentityApplicationManagementException("Error while storing permissions for application " + applicationName, e); } } /** * Updates the permissions of the application * * @param applicationName * @param permissions * @throws IdentityApplicationManagementException */ public static void updatePermissions(String applicationName, ApplicationPermission[] permissions) throws IdentityApplicationManagementException { applicationNode = getApplicationPermissionPath() + PATH_CONSTANT + applicationName; Registry tenantGovReg = CarbonContext.getThreadLocalCarbonContext().getRegistry( RegistryType.USER_GOVERNANCE); try { boolean exist = tenantGovReg.resourceExists(applicationNode); if (!exist) { Collection appRootNode = tenantGovReg.newCollection(); appRootNode.setProperty("name", applicationName); tenantGovReg.put(applicationNode, appRootNode); } Collection appNodeCollec = (Collection) tenantGovReg.get(applicationNode); String[] childern = appNodeCollec.getChildren(); // new permissions are null. deleting all permissions case if ((childern != null && childern.length > 0) && (permissions == null || permissions.length == 0)) { // there are permissions tenantGovReg.delete(applicationNode); } if (ArrayUtils.isEmpty(permissions)) { return; } // no permission exist for the application, create new if (childern == null || appNodeCollec.getChildCount() < 1) { addPermission(permissions, tenantGovReg); } else { // there are permission List<ApplicationPermission> loadPermissions = loadPermissions(applicationName); for (ApplicationPermission applicationPermission : loadPermissions) { tenantGovReg.delete(applicationNode + PATH_CONSTANT + applicationPermission.getValue()); } addPermission(permissions, tenantGovReg); } } catch (RegistryException e) { throw new IdentityApplicationManagementException("Error while storing permissions", e); } } private static void addPermission(ApplicationPermission[] permissions, Registry tenantGovReg) throws RegistryException { for (ApplicationPermission permission : permissions) { String permissionValue = permission.getValue(); if ("/".equals(permissionValue.substring(0, 1))) { //if permissions are starts with slash remove that permissionValue = permissionValue.substring(1); } String[] splitedPermission = permissionValue.split("/"); String permissinPath = applicationNode + PATH_CONSTANT; for (int i = 0; i < splitedPermission.length; i++) { permissinPath = permissinPath + splitedPermission[i] + PATH_CONSTANT; Collection permissionNode = tenantGovReg.newCollection(); permissionNode.setProperty("name", splitedPermission[i]); tenantGovReg.put(permissinPath, permissionNode); } } } /** * Loads the permissions of the application * * @param applicationName * @return * @throws IdentityApplicationManagementException */ public static List<ApplicationPermission> loadPermissions(String applicationName) throws IdentityApplicationManagementException { applicationNode = getApplicationPermissionPath() + PATH_CONSTANT + applicationName; Registry tenantGovReg = CarbonContext.getThreadLocalCarbonContext().getRegistry( RegistryType.USER_GOVERNANCE); try { boolean exist = tenantGovReg.resourceExists(applicationNode); if (!exist) { return Collections.emptyList(); } boolean loggedInUserChanged = false; String loggedInUser = CarbonContext.getThreadLocalCarbonContext().getUsername(); UserRealm realm = (UserRealm) CarbonContext.getThreadLocalCarbonContext().getUserRealm(); if (loggedInUser == null || !realm.getAuthorizationManager().isUserAuthorized( loggedInUser, applicationNode, UserMgtConstants.EXECUTE_ACTION)) { //Logged in user is not authorized to read the permission. // Temporarily change the user to the admin for reading the permission PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername( realm.getRealmConfiguration().getAdminUserName()); tenantGovReg = CarbonContext.getThreadLocalCarbonContext() .getRegistry(RegistryType.USER_GOVERNANCE); loggedInUserChanged = true; } paths.clear(); //clear current paths List<ApplicationPermission> permissions = new ArrayList<ApplicationPermission>(); permissionPath(tenantGovReg, applicationNode); //get permission paths recursively for (String permissionPath : paths) { ApplicationPermission permission; permission = new ApplicationPermission(); permission.setValue(permissionPath); permissions.add(permission); } if (loggedInUserChanged) { PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(loggedInUser); } return permissions; } catch (RegistryException | org.wso2.carbon.user.core.UserStoreException e) { throw new IdentityApplicationManagementException("Error while reading permissions", e); } } private static void permissionPath(Registry tenantGovReg, String permissionPath) throws RegistryException { Collection appCollection = (Collection) tenantGovReg.get(permissionPath); String[] childern = appCollection.getChildren(); if (childern == null || childern.length == 0) { paths.add(permissionPath.replace(applicationNode, "").substring(2)); } while (childern != null && childern.length != 0) { for (int i = 0; i < childern.length; i++) { permissionPath(tenantGovReg, childern[i]); } break; } } /** * Delete the resource * * @param applicationName * @throws IdentityApplicationManagementException */ public static void deletePermissions(String applicationName) throws IdentityApplicationManagementException { String applicationNode = getApplicationPermissionPath() + PATH_CONSTANT + applicationName; Registry tenantGovReg = CarbonContext.getThreadLocalCarbonContext().getRegistry( RegistryType.USER_GOVERNANCE); try { boolean exist = tenantGovReg.resourceExists(applicationNode); if (exist) { tenantGovReg.delete(applicationNode); } } catch (RegistryException e) { throw new IdentityApplicationManagementException("Error while storing permissions", e); } } /** * @param o1 * @param o2 * @return */ public static Property[] concatArrays(Property[] o1, Property[] o2) { Property[] ret = new Property[o1.length + o2.length]; System.arraycopy(o1, 0, ret, 0, o1.length); System.arraycopy(o2, 0, ret, o1.length, o2.length); return ret; } public static String getApplicationPermissionPath() { return CarbonConstants.UI_PERMISSION_NAME + RegistryConstants.PATH_SEPARATOR + APPLICATION_ROOT_PERMISSION; } /** * Get Property values * * @param tenantDomain Tenant domain * @param spIssuer SP Issuer * @param propertyNames Property names * @return Properties map * @throws IdentityApplicationManagementException */ protected Map<String, String> getPropertyValues(String tenantDomain, String spIssuer, List<String> propertyNames) throws IdentityApplicationManagementException { ServiceProvider serviceProvider = ApplicationMgtSystemConfig.getInstance().getApplicationDAO() .getApplication(spIssuer, tenantDomain); if (serviceProvider == null) { throw new IdentityApplicationManagementException( "No service provider exists in the provided tenant, with the given issuer id " + spIssuer); } Map<String, String> propKeyValueMap = new HashMap<String, String>(); InboundAuthenticationRequestConfig[] inboundAuthReqConfigs = serviceProvider.getInboundAuthenticationConfig() .getInboundAuthenticationRequestConfigs(); if (inboundAuthReqConfigs != null && inboundAuthReqConfigs.length > 0) { for (InboundAuthenticationRequestConfig authConfig : inboundAuthReqConfigs) { Property[] properties = authConfig.getProperties(); for (Property prop : properties) { if (propertyNames.contains(prop.getName())) { propKeyValueMap.put(prop.getName(), prop.getValue()); } } } } return propKeyValueMap; } }