diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java index fe2b5edd78..ec8c3a65f7 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java @@ -172,6 +172,9 @@ public class GroupManagementAdminServiceImpl implements GroupManagementAdminServ if (group == null) { return Response.status(Response.Status.BAD_REQUEST).build(); } + if (StringUtils.isEmpty(group.getOwner())) { + group.setOwner(PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername()); + } group.setStatus(DeviceGroupConstants.GroupStatus.ACTIVE); try { DeviceMgtAPIUtils.getGroupManagementProviderService().createGroup(group, DEFAULT_ADMIN_ROLE, DEFAULT_ADMIN_PERMISSIONS); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/authorization/GroupAccessAuthorizationService.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/authorization/GroupAccessAuthorizationService.java new file mode 100644 index 0000000000..1a1bdfb804 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/authorization/GroupAccessAuthorizationService.java @@ -0,0 +1,15 @@ +package io.entgra.device.mgt.core.device.mgt.common.authorization; + +public interface GroupAccessAuthorizationService { + + public boolean isUserAuthorized(int groupId, String username, String[] groupPermissions) + throws DeviceAccessAuthorizationException; + + public boolean isUserAuthorized(int groupId, String username) + throws DeviceAccessAuthorizationException; + + public boolean isUserAuthorized(int groupId, String[] groupPermissions) + throws DeviceAccessAuthorizationException; + + public boolean isUserAuthorized(int groupId) throws DeviceAccessAuthorizationException; +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java index 287b794c4c..0a26d2cb84 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java @@ -63,16 +63,36 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori return !DeviceManagementDataHolder.getInstance().requireDeviceAuthorization(deviceIdentifier.getType()); } //check for admin and ownership permissions - if (isAdmin(username, tenantId) || isDeviceOwner(deviceIdentifier, username)) { + if (isDeviceAdminUser(username, tenantId) || isDeviceOwner(deviceIdentifier, username)) { return true; } //check for group permissions - try { - return isSharedViaGroup(deviceIdentifier, username); - } catch (GroupManagementException | UserStoreException e) { - throw new DeviceAccessAuthorizationException("Unable to authorize the access to device : " + - deviceIdentifier.getId() + " for the user : " + - username, e); + if (groupPermissions == null || groupPermissions.length == 0) { + // if group permissions not specified, check whether roles are shared. + try { + return isSharedViaGroup(deviceIdentifier, username); + } catch (GroupManagementException | UserStoreException e) { + throw new DeviceAccessAuthorizationException("Unable to authorize the access to device : " + + deviceIdentifier.getId() + " for the user : " + + username, e); + } + } else { + // if group permissions specified, check whether that permission is available in shared role + try { + boolean isAuthorized = true; + for (String groupPermission : groupPermissions) { + if (!isAuthorizedViaSharedGroup(deviceIdentifier, username, groupPermission)) { + //if at least one failed, authorizations fails and break the loop + isAuthorized = false; + break; + } + } + return isAuthorized; + } catch (DeviceAccessAuthorizationException e) { + throw new DeviceAccessAuthorizationException("Unable to authorize the access to device : " + + deviceIdentifier.getId() + " for the user : " + + username, e); + } } } @@ -94,6 +114,30 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori return false; } + private boolean isAuthorizedViaSharedGroup(DeviceIdentifier deviceIdentifier, String username, String groupPermission) + throws DeviceAccessAuthorizationException { + try { + List groupsWithDevice = DeviceManagementDataHolder.getInstance() + .getGroupManagementProviderService().getGroups(deviceIdentifier, false); + UserRealm userRealm = DeviceManagementDataHolder.getInstance().getRealmService() + .getTenantUserRealm(getTenantId()); + String[] userRoles = userRealm.getUserStoreManager().getRoleListOfUser(username); + for (DeviceGroup deviceGroup : groupsWithDevice) { + List sharingRoles = DeviceManagementDataHolder.getInstance() + .getGroupManagementProviderService().getRoles(deviceGroup.getGroupId()); + for (String role : userRoles) { + if (sharingRoles.contains(role) && userRealm.getAuthorizationManager(). + isRoleAuthorized(role, groupPermission, CarbonConstants.UI_PERMISSION_ACTION)) { + return true; + } + } + } + return false; + } catch (GroupManagementException | UserStoreException e) { + throw new DeviceAccessAuthorizationException("unable to authorized via shared role, " + groupPermission); + } + } + @Override public boolean isUserAuthorized(DeviceIdentifier deviceIdentifier, String username) throws DeviceAccessAuthorizationException { @@ -116,8 +160,8 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori String username = this.getUserName(); int tenantId = this.getTenantId(); try { - return isAdminUser(username, tenantId); - } catch (UserStoreException e) { + return isDeviceAdminUser(username, tenantId); + } catch (DeviceAccessAuthorizationException e) { throw new DeviceAccessAuthorizationException("Unable to check the admin permissions of user : " + username + " in tenant : " + tenantId, e); } @@ -132,7 +176,7 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori return null; } DeviceAuthorizationResult deviceAuthorizationResult = new DeviceAuthorizationResult(); - if (isAdmin(username, tenantId)) { + if (isDeviceAdminUser(username, tenantId)) { deviceAuthorizationResult.setAuthorizedDevices(deviceIdentifiers); return deviceAuthorizationResult; } @@ -149,7 +193,7 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori //check for group permissions boolean isAuthorized = true; for (String groupPermission : groupPermissions) { - if (!isAuthorizedViaGroup(username, deviceIdentifier, groupPermission)) { + if (!isAuthorizedViaSharedGroup(deviceIdentifier, username, groupPermission)) { //if at least one failed, authorizations fails and break the loop isAuthorized = false; break; @@ -160,7 +204,7 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori } else { deviceAuthorizationResult.addUnauthorizedDevice(deviceIdentifier); } - } catch (GroupManagementException e) { + } catch (DeviceAccessAuthorizationException e) { throw new DeviceAccessAuthorizationException("Unable to authorize the access to device : " + deviceIdentifier.getId() + " for the user : " + username, e); @@ -188,36 +232,36 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori return isUserAuthorized(deviceIdentifiers, this.getUserName(), groupPermissions); } - private boolean isAdmin(String username, int tenantId) - throws DeviceAccessAuthorizationException { - try { - //Check for admin users. If the user is an admin user we authorize the access to that device. - return (isAdminUser(username, tenantId)); - } catch (UserStoreException e) { - throw new DeviceAccessAuthorizationException("Unable to authorize the access for the user : " + - username, e); - } - } +// private boolean isAdmin(String username, int tenantId) +// throws DeviceAccessAuthorizationException { +// try { +// //Check for admin users. If the user is an admin user we authorize the access to that device. +// return (isDeviceAdminUser(username, tenantId)); +// } catch (DeviceAccessAuthorizationException e) { +// throw new DeviceAccessAuthorizationException("Unable to authorize the access for the user : " + +// username, e); +// } +// } - private boolean isAuthorizedViaGroup(String username, DeviceIdentifier deviceIdentifier, String groupPermission) - throws GroupManagementException { - List authorizedGroups = - DeviceManagementDataHolder.getInstance().getGroupManagementProviderService() - .getGroups(username, groupPermission, false); - List groupsWithDevice = - DeviceManagementDataHolder.getInstance().getGroupManagementProviderService() - .getGroups(deviceIdentifier, false); - for (DeviceGroup group : authorizedGroups) { - Iterator groupsWithDeviceIterator = groupsWithDevice.iterator(); - while (groupsWithDeviceIterator.hasNext()) { - DeviceGroup deviceGroup = groupsWithDeviceIterator.next(); - if (deviceGroup.getGroupId() == group.getGroupId()) { - return true; - } - } - } - return false; - } +// private boolean isAuthorizedViaGroup(String username, DeviceIdentifier deviceIdentifier, String groupPermission) +// throws GroupManagementException { +// List authorizedGroups = +// DeviceManagementDataHolder.getInstance().getGroupManagementProviderService() +// .getGroups(username, groupPermission, false); +// List groupsWithDevice = +// DeviceManagementDataHolder.getInstance().getGroupManagementProviderService() +// .getGroups(deviceIdentifier, false); +// for (DeviceGroup group : authorizedGroups) { +// Iterator groupsWithDeviceIterator = groupsWithDevice.iterator(); +// while (groupsWithDeviceIterator.hasNext()) { +// DeviceGroup deviceGroup = groupsWithDeviceIterator.next(); +// if (deviceGroup.getGroupId() == group.getGroupId()) { +// return true; +// } +// } +// } +// return false; +// } private boolean isDeviceOwner(DeviceIdentifier deviceIdentifier, String username) throws DeviceAccessAuthorizationException { @@ -232,15 +276,20 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori } } - private boolean isAdminUser(String username, int tenantId) throws UserStoreException { - UserRealm userRealm = DeviceManagementDataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId); - if (userRealm != null && userRealm.getAuthorizationManager() != null) { - return userRealm.getAuthorizationManager() - .isUserAuthorized(removeTenantDomain(username), - PermissionUtils.getAbsolutePermissionPath(CDM_ADMIN_PERMISSION), - CarbonConstants.UI_PERMISSION_ACTION); + private boolean isDeviceAdminUser(String username, int tenantId) throws DeviceAccessAuthorizationException { + try { + UserRealm userRealm = DeviceManagementDataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId); + if (userRealm != null && userRealm.getAuthorizationManager() != null) { + return userRealm.getAuthorizationManager() + .isUserAuthorized(removeTenantDomain(username), + PermissionUtils.getAbsolutePermissionPath(CDM_ADMIN_PERMISSION), + CarbonConstants.UI_PERMISSION_ACTION); + } + return false; + } catch (UserStoreException e) { + throw new DeviceAccessAuthorizationException("Unable to authorize the access for the user : " + + username, e); } - return false; } private String getUserName() { diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/authorization/GroupAccessAuthorizationServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/authorization/GroupAccessAuthorizationServiceImpl.java new file mode 100644 index 0000000000..cf7e2ca47d --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/authorization/GroupAccessAuthorizationServiceImpl.java @@ -0,0 +1,166 @@ +package io.entgra.device.mgt.core.device.mgt.core.authorization; + +import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; +import io.entgra.device.mgt.core.device.mgt.common.authorization.DeviceAccessAuthorizationException; +import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAccessAuthorizationService; +import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException; +import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroup; +import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupManagementException; +import io.entgra.device.mgt.core.device.mgt.common.permission.mgt.Permission; +import io.entgra.device.mgt.core.device.mgt.common.permission.mgt.PermissionManagementException; +import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder; +import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionUtils; +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.user.api.UserRealm; +import org.wso2.carbon.user.api.UserStoreException; + +import java.util.List; + +public class GroupAccessAuthorizationServiceImpl implements GroupAccessAuthorizationService { + + private final static String GROUP_ADMIN_PERMISSION = "/device-mgt/devices/any-group/permitted-actions-under-owning-group"; + private final static String GROUP_ADMIN = "Group Management Administrator"; + private static Log log = LogFactory.getLog(DeviceAccessAuthorizationServiceImpl.class); + + public GroupAccessAuthorizationServiceImpl() { + try { + this.addAdminPermissionToRegistry(); + } catch (PermissionManagementException e) { + log.error("Unable to add the group-admin permission to the registry.", e); + } + } + + @Override + public boolean isUserAuthorized(int groupId, String username, String[] groupPermissions) + throws DeviceAccessAuthorizationException { + int tenantId = this.getTenantId(); + if (username == null || username.isEmpty()) { + username = this.getUserName(); + } + //check for admin and ownership permissions + if (isGroupAdminUser(username, tenantId) || isGroupOwner(groupId, username)) { + return true; + } + + // if group owner + if (isGroupOwner(groupId, username)) { + //check for group permissions + if (groupPermissions == null || groupPermissions.length == 0) { + return false; + } else { + // if group permissions specified, check whether that permission is available in any user role of the group owner + try { + UserRealm userRealm = DeviceManagementDataHolder.getInstance().getRealmService() + .getTenantUserRealm(getTenantId()); + String[] userRoles = userRealm.getUserStoreManager().getRoleListOfUser(username); + boolean isAuthorized = true; + for (String groupPermission : groupPermissions) { + for (String role : userRoles) { + if (!userRealm.getAuthorizationManager(). + isRoleAuthorized(role, groupPermission, CarbonConstants.UI_PERMISSION_ACTION)) { + isAuthorized = false; + break; + } + } + } + return isAuthorized; + } catch (UserStoreException e) { + throw new DeviceAccessAuthorizationException("Unable to authorize the access to group : " + + groupId + " for the user : " + + username, e); + } + } + } + + return false; + } + + @Override + public boolean isUserAuthorized(int groupId, String username) + throws DeviceAccessAuthorizationException { + return isUserAuthorized(groupId, username, null); + } + + @Override + public boolean isUserAuthorized(int groupId, String[] groupPermissions) + throws DeviceAccessAuthorizationException { + return isUserAuthorized(groupId, this.getUserName(), groupPermissions); + } + + @Override + public boolean isUserAuthorized(int groupId) throws DeviceAccessAuthorizationException { + return isUserAuthorized(groupId, this.getUserName(), null); + } + + public boolean isGroupAdminUser() throws DeviceAccessAuthorizationException { + String username = this.getUserName(); + int tenantId = this.getTenantId(); + try { + return isGroupAdminUser(username, tenantId); + } catch (DeviceAccessAuthorizationException e) { + throw new DeviceAccessAuthorizationException("Unable to check the admin permissions of user : " + + username + " in tenant : " + tenantId, e); + } + } + + private boolean isGroupOwner(int groupId, String username) + throws DeviceAccessAuthorizationException { + //Check for group ownership. If the user is the owner of the group we allow the access. + try { + DeviceGroup group = DeviceManagementDataHolder.getInstance(). + getGroupManagementProviderService().getGroup(groupId, false); + return username.equals(group.getOwner()); + } catch (GroupManagementException e) { + throw new DeviceAccessAuthorizationException("Unable to authorize the access to group : " + + groupId + " for the user : " + + username, e); + } + } + + private boolean isGroupAdminUser(String username, int tenantId) throws DeviceAccessAuthorizationException { + try { + UserRealm userRealm = DeviceManagementDataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId); + if (userRealm != null && userRealm.getAuthorizationManager() != null) { + return userRealm.getAuthorizationManager() + .isUserAuthorized(removeTenantDomain(username), + PermissionUtils.getAbsolutePermissionPath(GROUP_ADMIN_PERMISSION), + CarbonConstants.UI_PERMISSION_ACTION); + } + return false; + } catch (UserStoreException e) { + throw new DeviceAccessAuthorizationException("Unable to authorize the access for the user : " + + username, e); + } + } + + private String getUserName() { + String username = CarbonContext.getThreadLocalCarbonContext().getUsername(); + if (username != null && !username.isEmpty()) { + return removeTenantDomain(username); + } + return null; + } + + private String removeTenantDomain(String username) { + String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + if (username.endsWith(tenantDomain)) { + return username.substring(0, username.lastIndexOf("@")); + } + return username; + } + + private int getTenantId() { + return CarbonContext.getThreadLocalCarbonContext().getTenantId(); + } + + private boolean addAdminPermissionToRegistry() throws PermissionManagementException { + Permission permission = new Permission(); + permission.setName(GROUP_ADMIN); + permission.setPath(PermissionUtils.getAbsolutePermissionPath(GROUP_ADMIN_PERMISSION)); + return PermissionUtils.putPermission(permission); + } + +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementDataHolder.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementDataHolder.java index 6736874487..48d573a5fa 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementDataHolder.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementDataHolder.java @@ -20,6 +20,7 @@ package io.entgra.device.mgt.core.device.mgt.core.internal; import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices; import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServices; +import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAccessAuthorizationService; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService; import org.wso2.carbon.context.PrivilegedCarbonContext; @@ -78,6 +79,7 @@ public class DeviceManagementDataHolder { private ConfigurationContextService configurationContextService; private final HashMap requireDeviceAuthorization = new HashMap<>(); private DeviceAccessAuthorizationService deviceAccessAuthorizationService; + private GroupAccessAuthorizationService groupAccessAuthorizationService; private GroupManagementProviderService groupManagementProviderService; private TaskService taskService; private EmailSenderService emailSenderService; @@ -447,4 +449,12 @@ public class DeviceManagementDataHolder { public void setPublisherRESTAPIServices(PublisherRESTAPIServices publisherRESTAPIServices) { this.publisherRESTAPIServices = publisherRESTAPIServices; } + + public GroupAccessAuthorizationService getGroupAccessAuthorizationService() { + return groupAccessAuthorizationService; + } + + public void setGroupAccessAuthorizationService(GroupAccessAuthorizationService groupAccessAuthorizationService) { + this.groupAccessAuthorizationService = groupAccessAuthorizationService; + } } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementServiceComponent.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementServiceComponent.java index b3bc1f2f0d..b2e1529f40 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementServiceComponent.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementServiceComponent.java @@ -17,7 +17,9 @@ */ package io.entgra.device.mgt.core.device.mgt.core.internal; +import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAccessAuthorizationService; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; +import io.entgra.device.mgt.core.device.mgt.core.authorization.GroupAccessAuthorizationServiceImpl; import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.DeviceStatusManagementServiceImpl; import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService; import org.apache.commons.logging.Log; @@ -353,6 +355,12 @@ public class DeviceManagementServiceComponent { bundleContext.registerService(DeviceAccessAuthorizationService.class.getName(), deviceAccessAuthorizationService, null); + /* Registering GroupAccessAuthorization Service */ + GroupAccessAuthorizationService groupAccessAuthorizationService = new GroupAccessAuthorizationServiceImpl(); + DeviceManagementDataHolder.getInstance().setGroupAccessAuthorizationService(groupAccessAuthorizationService); + bundleContext.registerService(GroupAccessAuthorizationService.class.getName(), + groupAccessAuthorizationService, null); + /* Registering Geo Service */ GeoLocationProviderService geoService = new GeoLocationProviderServiceImpl(); DeviceManagementDataHolder.getInstance().setGeoLocationProviderService(geoService);