From 1dbc1d7b0d35fa276c6891d862cad17749b3c373 Mon Sep 17 00:00:00 2001 From: "amalka.subasinghe" Date: Tue, 20 Feb 2024 11:32:23 +0530 Subject: [PATCH] device/group authorization improvement --- .../api/AccessAuthorizationService.java | 181 ++++++++++++++++++ .../impl/AccessAuthorizationServiceImpl.java | 95 +++++++++ .../service/impl/DeviceAgentServiceImpl.java | 13 +- .../impl/DeviceManagementServiceImpl.java | 9 +- .../impl/GroupManagementServiceImpl.java | 1 + .../impl/PolicyManagementServiceImpl.java | 5 +- .../GroupManagementAdminServiceImpl.java | 3 + .../mgt/api/jaxrs/util/DeviceMgtAPIUtils.java | 17 +- .../service/impl/DeviceAgentServiceTest.java | 24 +-- .../impl/DeviceManagementServiceImplTest.java | 2 +- .../DeviceAccessAuthorizationService.java | 46 ----- .../DeviceAuthorizationRequest.java | 68 +++++++ .../GroupAccessAuthorizationException.java | 61 ++++++ .../GroupAccessAuthorizationService.java | 16 ++ .../GroupAuthorizationRequest.java | 58 ++++++ .../GroupAuthorizationResult.java | 56 ++++++ .../DeviceAccessAuthorizationServiceImpl.java | 145 ++++++-------- .../GroupAccessAuthorizationServiceImpl.java | 173 +++++++++++++++++ .../impl/DeviceInformationManagerImpl.java | 5 +- .../internal/DeviceManagementDataHolder.java | 10 + .../DeviceManagementServiceComponent.java | 8 + .../operation/mgt/OperationManagerImpl.java | 9 +- .../mgt/PermissionManagerServiceImpl.java | 13 ++ .../GroupManagementProviderServiceImpl.java | 19 +- .../DeviceAccessAuthorizationServiceTest.java | 8 +- .../authorizer/PermissionAuthorizer.java | 1 + 26 files changed, 884 insertions(+), 162 deletions(-) create mode 100644 components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/AccessAuthorizationService.java create mode 100644 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/AccessAuthorizationServiceImpl.java create mode 100644 components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/authorization/DeviceAuthorizationRequest.java create mode 100644 components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/authorization/GroupAccessAuthorizationException.java create mode 100644 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 create mode 100644 components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/authorization/GroupAuthorizationRequest.java create mode 100644 components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/authorization/GroupAuthorizationResult.java create mode 100644 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 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/api/AccessAuthorizationService.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/api/AccessAuthorizationService.java new file mode 100644 index 00000000000..1de058f4fc3 --- /dev/null +++ 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/api/AccessAuthorizationService.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.api; + +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.ErrorResponse; +import io.entgra.device.mgt.core.device.mgt.common.authorization.DeviceAuthorizationRequest; +import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAuthorizationRequest; +import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAuthorizationResult; +import io.swagger.annotations.*; +import org.apache.axis2.transport.http.HTTPConstants; + +import javax.validation.Valid; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@SwaggerDefinition( + info = @Info( + version = "1.0.0", + title = "", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = "name", value = "AccessAuthorizationService"), + @ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/access"), + }) + } + ), + tags = { + @Tag(name = "device_management", description = "") + } +) +@Path("/access") +@Api(value = "AccessAuthorizationService", description = "This API carries all device group management related " + + "access authorization") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public interface AccessAuthorizationService { + + @POST + @Path("/device") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_GET, + value = "check device access authorization", + notes = "Returns device access acutorization info", + tags = "device_management" + ) + @ApiResponses( + value = { + @ApiResponse( + code = 201, + message = "Created. \n Device group has successfully been created", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The URL of the added group."), + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time" + + ".\n" + "Used by caches, or in conditional requests.") + } + ), + @ApiResponse( + code = 303, + message = "See Other. \n Source can be retrieved from the URL specified at the Location " + + "header.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The Source URL of the document.")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Current logged in user is not authorized for this request", + response = ErrorResponse.class), + @ApiResponse( + code = 415, + message = "Unsupported media type. \n The entity of the request was in a not supported " + + "format."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while checking access", + response = ErrorResponse.class) + }) + Response checkDeviceAccess( + @ApiParam( + name = "deviceAccessRequest", + value = "Define the device access request object with data.", + required = true) + @Valid DeviceAuthorizationRequest deviceAuthorizationRequest); + + @POST + @Path("/group") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_GET, + value = "check device access authorization", + notes = "Returns device access acutorization info", + tags = "device_management" + ) + @ApiResponses( + value = { + @ApiResponse( + code = 201, + message = "Created. \n Device group has successfully been created", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The URL of the added group."), + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time" + + ".\n" + "Used by caches, or in conditional requests.") + } + ), + @ApiResponse( + code = 303, + message = "See Other. \n Source can be retrieved from the URL specified at the Location " + + "header.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The Source URL of the document.")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Current logged in user is not authorized for this request", + response = ErrorResponse.class), + @ApiResponse( + code = 415, + message = "Unsupported media type. \n The entity of the request was in a not supported " + + "format."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while checking access", + response = ErrorResponse.class) + }) + Response checkGroupAccess( + @ApiParam( + name = "groupAccessRequest", + value = "Define the group access request object with data.", + required = true) + @Valid GroupAuthorizationRequest request); +} 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/AccessAuthorizationServiceImpl.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/AccessAuthorizationServiceImpl.java new file mode 100644 index 00000000000..f6d555a2736 --- /dev/null +++ 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/AccessAuthorizationServiceImpl.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl; + +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.api.AccessAuthorizationService; +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.DeviceMgtAPIUtils; +import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; +import io.entgra.device.mgt.core.device.mgt.common.authorization.*; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.List; + + +public class AccessAuthorizationServiceImpl implements AccessAuthorizationService { + + private static final Log log = LogFactory.getLog(AccessAuthorizationServiceImpl.class); + @Override + public Response checkDeviceAccess(DeviceAuthorizationRequest deviceAuthorizationRequest) { + + if (StringUtils.isEmpty(deviceAuthorizationRequest.getType())) { + String msg = "device type not specified"; + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + + if (deviceAuthorizationRequest.getDeviceIds().isEmpty()) { + String msg = "device ids not specified"; + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + + if (deviceAuthorizationRequest.getPermissions().isEmpty()) { + String msg = "permissions not specified"; + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + + List deviceIdentifiers = new ArrayList<>(); + for(String id : deviceAuthorizationRequest.getDeviceIds()) { + DeviceIdentifier identifier = new DeviceIdentifier(id, deviceAuthorizationRequest.getType()); + deviceIdentifiers.add(identifier); + } + try { + DeviceAuthorizationResult result = DeviceMgtAPIUtils.getDeviceAccessAuthorizationService() + .isUserAuthorized(deviceIdentifiers, deviceAuthorizationRequest.getUsername(), + deviceAuthorizationRequest.getPermissions().toArray(new String[0])); + return Response.status(Response.Status.OK).entity(result).build(); + } catch (DeviceAccessAuthorizationException e) { + String msg = "Error occurred while checking access info"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @Override + public Response checkGroupAccess(GroupAuthorizationRequest request) { + + if (request.getGroupIds().isEmpty()) { + String msg = "group ids not specified"; + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + + if (request.getPermissions().isEmpty()) { + String msg = "permissions not specified"; + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + + try { + GroupAuthorizationResult result = DeviceMgtAPIUtils.getGroupAccessAuthorizationService() + .isUserAuthorized(request.getGroupIds(), request.getUsername(), + request.getPermissions().toArray(new String[0])); + return Response.status(Response.Status.OK).entity(result).build(); + } catch (GroupAccessAuthorizationException e) { + String msg = "Error occurred while checking access info"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } +} 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/DeviceAgentServiceImpl.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/DeviceAgentServiceImpl.java index 32313062b6f..4231ecc41ea 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/DeviceAgentServiceImpl.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/DeviceAgentServiceImpl.java @@ -21,6 +21,7 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonParser; +import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; import org.apache.axis2.AxisFault; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -167,7 +168,9 @@ public class DeviceAgentServiceImpl implements DeviceAgentService { DeviceMgtAPIUtils.getDeviceAccessAuthorizationService(); boolean status; try { - status = deviceAccessAuthorizationService.isUserAuthorized(new DeviceIdentifier(id, type)); + String requiredPermission = PermissionManagerServiceImpl.getInstance().getRequiredPermission(); + String[] requiredPermissions = new String[] {requiredPermission}; + status = deviceAccessAuthorizationService.isUserAuthorized(new DeviceIdentifier(id, type), requiredPermissions); } catch (DeviceAccessAuthorizationException e) { String msg = "Error occurred while modifying enrollment of the Android device that carries the id '" + id + "'"; @@ -229,8 +232,10 @@ public class DeviceAgentServiceImpl implements DeviceAgentService { String msg = "invalid payload structure"; return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } else { + String requiredPermission = PermissionManagerServiceImpl.getInstance().getRequiredPermission(); + String[] requiredPermissions = new String[] {requiredPermission}; boolean authorized = DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized - (new DeviceIdentifier(type, deviceId)); + (new DeviceIdentifier(type, deviceId), requiredPermissions); if (!authorized) { String msg = "Does not have permission to access the device."; return Response.status(Response.Status.UNAUTHORIZED).entity(msg).build(); @@ -329,8 +334,10 @@ public class DeviceAgentServiceImpl implements DeviceAgentService { String msg = "Invalid payload structure"; return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } else { + String requiredPermission = PermissionManagerServiceImpl.getInstance().getRequiredPermission(); + String[] requiredPermissions = new String[] {requiredPermission}; boolean authorized = DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized - (new DeviceIdentifier(type, deviceId)); + (new DeviceIdentifier(type, deviceId), requiredPermissions); if (!authorized) { String msg = "Does not have permission to access the device."; return Response.status(Response.Status.UNAUTHORIZED).entity(msg).build(); 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/DeviceManagementServiceImpl.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/DeviceManagementServiceImpl.java index d8f028c9285..58259e19c88 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/DeviceManagementServiceImpl.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/DeviceManagementServiceImpl.java @@ -28,6 +28,7 @@ import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionMan import io.entgra.device.mgt.core.application.mgt.core.util.HelperUtil; import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl.util.DisenrollRequest; import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.DeviceMgtUtil; +import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; @@ -580,7 +581,9 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { String authorizedUser = CarbonContext.getThreadLocalCarbonContext().getUsername(); DeviceIdentifier deviceIdentifier = new DeviceIdentifier(id, type); // check whether the user is authorized - if (!deviceAccessAuthorizationService.isUserAuthorized(deviceIdentifier, authorizedUser)) { + String requiredPermission = PermissionManagerServiceImpl.getInstance().getRequiredPermission(); + String[] requiredPermissions = new String[] {requiredPermission}; + if (!deviceAccessAuthorizationService.isUserAuthorized(deviceIdentifier, authorizedUser, requiredPermissions)) { String msg = "User '" + authorizedUser + "' is not authorized to retrieve the given device id '" + id + "'"; log.error(msg); return Response.status(Response.Status.UNAUTHORIZED).entity( @@ -716,7 +719,9 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { } DeviceIdentifier deviceIdentifier = new DeviceIdentifier(id, device.getType()); // check whether the user is authorized - if (!deviceAccessAuthorizationService.isUserAuthorized(deviceIdentifier, authorizedUser)) { + String requiredPermission = PermissionManagerServiceImpl.getInstance().getRequiredPermission(); + String[] requiredPermissions = new String[] {requiredPermission}; + if (!deviceAccessAuthorizationService.isUserAuthorized(deviceIdentifier, authorizedUser, requiredPermissions)) { String message = "User '" + authorizedUser + "' is not authorized to retrieve the given " + "device id '" + id + "'"; log.error(message); 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/GroupManagementServiceImpl.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/GroupManagementServiceImpl.java index fc8f080b07c..f9e7df536da 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/GroupManagementServiceImpl.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/GroupManagementServiceImpl.java @@ -27,6 +27,7 @@ import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupAlreadyExistEx import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupManagementException; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupNotExistException; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.RoleDoesNotExistException; +import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; import io.entgra.device.mgt.core.device.mgt.extensions.logger.spi.EntgraLogger; import io.entgra.device.mgt.core.notification.logger.GroupMgtLogContext; import io.entgra.device.mgt.core.notification.logger.impl.EntgraGroupMgtLoggerImpl; 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/PolicyManagementServiceImpl.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/PolicyManagementServiceImpl.java index 2a8e6357cc7..311b4292a7a 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/PolicyManagementServiceImpl.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/PolicyManagementServiceImpl.java @@ -18,6 +18,7 @@ package io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl; import io.entgra.device.mgt.core.device.mgt.common.PolicyPaginationRequest; +import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; @@ -85,7 +86,9 @@ public class PolicyManagementServiceImpl implements PolicyManagementService { PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); String username = threadLocalCarbonContext.getUsername(); try { - if (!deviceAccessAuthorizationService.isUserAuthorized(deviceIdentifier, username)) { + String requiredPermission = PermissionManagerServiceImpl.getInstance().getRequiredPermission(); + String[] requiredPermissions = new String[] {requiredPermission}; + if (!deviceAccessAuthorizationService.isUserAuthorized(deviceIdentifier, username, requiredPermissions)) { return Response.status(Response.Status.UNAUTHORIZED).entity( new ErrorResponse.ErrorResponseBuilder().setMessage ("Current logged in user is not authorized to add policies").build()).build(); 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 fe2b5edd781..ec8c3a65f72 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.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/util/DeviceMgtAPIUtils.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/util/DeviceMgtAPIUtils.java index 6de5d1d1ca8..885d521389a 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/util/DeviceMgtAPIUtils.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/util/DeviceMgtAPIUtils.java @@ -21,7 +21,9 @@ package io.entgra.device.mgt.core.device.mgt.api.jaxrs.util; import io.entgra.device.mgt.core.apimgt.webapp.publisher.APIPublisherService; import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager; import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager; +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.permission.mgt.PermissionManagerServiceImpl; import org.apache.axis2.AxisFault; import org.apache.axis2.client.Options; import org.apache.axis2.java.security.SSLProtocolSocketFactory; @@ -342,6 +344,17 @@ public class DeviceMgtAPIUtils { return deviceAccessAuthorizationService; } + public static GroupAccessAuthorizationService getGroupAccessAuthorizationService() { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + GroupAccessAuthorizationService groupAccessAuthorizationService = + (GroupAccessAuthorizationService) ctx.getOSGiService(GroupAccessAuthorizationService.class, null); + if (groupAccessAuthorizationService == null) { + String msg = "GroupAccessAuthorizationService service has not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + return groupAccessAuthorizationService; + } public static GroupManagementProviderService getGroupManagementProviderService() { PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); GroupManagementProviderService groupManagementProviderService = @@ -1111,7 +1124,9 @@ public class DeviceMgtAPIUtils { RequestValidationUtil.validateDeviceIdentifier(deviceType, identifier); DeviceIdentifier deviceIdentifier = new DeviceIdentifier(identifier, deviceType); - if (!getDeviceAccessAuthorizationService().isUserAuthorized(deviceIdentifier, authorizedUser)) { + String requiredPermission = PermissionManagerServiceImpl.getInstance().getRequiredPermission(); + String[] requiredPermissions = new String[] {requiredPermission}; + if (!getDeviceAccessAuthorizationService().isUserAuthorized(deviceIdentifier, authorizedUser, requiredPermissions)) { String msg = "User '" + authorizedUser + "' is not authorized to retrieve the given device id '" + identifier + "'"; log.error(msg); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceAgentServiceTest.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceAgentServiceTest.java index e32761b0e67..d7ac8671ee0 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceAgentServiceTest.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceAgentServiceTest.java @@ -285,7 +285,7 @@ public class DeviceAgentServiceTest { Device testDevice = DeviceMgtAPITestHelper.generateDummyDevice(TEST_DEVICE_TYPE, TEST_DEVICE_IDENTIFIER); Mockito.when(this.deviceManagementProviderService .getDevice(Mockito.any(DeviceIdentifier.class), Mockito.any(Boolean.class))).thenReturn(testDevice); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenThrow(new DeviceAccessAuthorizationException()); Response response = deviceAgentService.updateDevice(TEST_DEVICE_TYPE, TEST_DEVICE_IDENTIFIER, testDevice); Assert.assertNotNull(response, "Response should not be null"); @@ -305,7 +305,7 @@ public class DeviceAgentServiceTest { Device testDevice = DeviceMgtAPITestHelper.generateDummyDevice(TEST_DEVICE_TYPE, TEST_DEVICE_IDENTIFIER); Mockito.when(this.deviceManagementProviderService .getDevice(Mockito.any(DeviceIdentifier.class), Mockito.any(Boolean.class))).thenReturn(testDevice); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenReturn(false); Response response = deviceAgentService.updateDevice(TEST_DEVICE_TYPE, TEST_DEVICE_IDENTIFIER, testDevice); Assert.assertNotNull(response, "Response should not be null"); @@ -327,7 +327,7 @@ public class DeviceAgentServiceTest { Device testDevice = DeviceMgtAPITestHelper.generateDummyDevice(TEST_DEVICE_TYPE, TEST_DEVICE_IDENTIFIER); Mockito.when(this.deviceManagementProviderService .getDevice(Mockito.any(DeviceIdentifier.class), Mockito.any(Boolean.class))).thenReturn(testDevice); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenReturn(true); Mockito.when(this.deviceManagementProviderService.modifyEnrollment(Mockito.any())).thenReturn(false); Response response = deviceAgentService.updateDevice(TEST_DEVICE_TYPE, TEST_DEVICE_IDENTIFIER, testDevice); @@ -350,7 +350,7 @@ public class DeviceAgentServiceTest { Device testDevice = DeviceMgtAPITestHelper.generateDummyDevice(TEST_DEVICE_TYPE, TEST_DEVICE_IDENTIFIER); Mockito.when(this.deviceManagementProviderService .getDevice(Mockito.any(DeviceIdentifier.class), Mockito.any(Boolean.class))).thenReturn(testDevice); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenReturn(true); Mockito.when(this.deviceManagementProviderService.modifyEnrollment(Mockito.any())) .thenThrow(new DeviceManagementException()); @@ -372,7 +372,7 @@ public class DeviceAgentServiceTest { "getAuthenticatedUser")).toReturn(AUTHENTICATED_USER); Device testDevice = DeviceMgtAPITestHelper.generateDummyDevice(TEST_DEVICE_TYPE, TEST_DEVICE_IDENTIFIER); Mockito.when(this.deviceManagementProviderService.getDevice(Mockito.any(DeviceIdentifier.class), Mockito.any(Boolean.class))).thenReturn(testDevice); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenReturn(true); Mockito.when(this.deviceManagementProviderService.modifyEnrollment(Mockito.any())).thenReturn((true)); Response response = deviceAgentService.updateDevice(TEST_DEVICE_TYPE, TEST_DEVICE_IDENTIFIER, testDevice); @@ -408,7 +408,7 @@ public class DeviceAgentServiceTest { .toReturn(this.privilegedCarbonContext); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceAccessAuthorizationService")).toReturn(this.deviceAccessAuthorizationService); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenReturn(false); Mockito.when(this.privilegedCarbonContext.getTenantDomain()) .thenReturn(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); @@ -432,7 +432,7 @@ public class DeviceAgentServiceTest { .toReturn(this.privilegedCarbonContext); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceAccessAuthorizationService")).toReturn(this.deviceAccessAuthorizationService); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenThrow(new DeviceAccessAuthorizationException()); Mockito.when(this.privilegedCarbonContext.getTenantDomain()) .thenReturn(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); @@ -457,7 +457,7 @@ public class DeviceAgentServiceTest { .toReturn(this.privilegedCarbonContext); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceAccessAuthorizationService")).toReturn(this.deviceAccessAuthorizationService); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenReturn(true); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getEventStreamAdminServiceStub")) .toReturn(this.eventStreamAdminServiceStub); @@ -485,7 +485,7 @@ public class DeviceAgentServiceTest { .toReturn(this.privilegedCarbonContext); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceAccessAuthorizationService")).toReturn(this.deviceAccessAuthorizationService); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenReturn(true); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getEventStreamAdminServiceStub")) .toThrow(new AxisFault("")); @@ -511,7 +511,7 @@ public class DeviceAgentServiceTest { .toReturn(this.privilegedCarbonContext); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceAccessAuthorizationService")).toReturn(this.deviceAccessAuthorizationService); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenReturn(true); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getEventStreamAdminServiceStub")) .toThrow(new RemoteException()); @@ -539,7 +539,7 @@ public class DeviceAgentServiceTest { .toReturn(this.privilegedCarbonContext); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceAccessAuthorizationService")).toReturn(this.deviceAccessAuthorizationService); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenReturn(true); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getEventStreamAdminServiceStub")) .toThrow(new JWTClientException()); @@ -567,7 +567,7 @@ public class DeviceAgentServiceTest { .toReturn(this.privilegedCarbonContext); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceAccessAuthorizationService")).toReturn(this.deviceAccessAuthorizationService); - Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class))) + Mockito.when(this.deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), Mockito.any(String[].class))) .thenReturn(true); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getEventStreamAdminServiceStub")) .toThrow(new UserStoreException()); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java index 2ef62073bd5..63bb401d610 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java @@ -215,7 +215,7 @@ public class DeviceManagementServiceImplTest { Mockito.when(carbonContext.getTenantId()).thenReturn(-1234); Mockito.when(carbonContext.getUsername()).thenReturn(DEFAULT_USERNAME); Mockito.when(deviceAccessAuthorizationService.isUserAuthorized(Mockito.any(DeviceIdentifier.class), - Mockito.anyString())).thenReturn(true); + Mockito.anyString(), Mockito.any(String[].class))).thenReturn(true); Response response = this.deviceManagementService .getDeviceByID(TEST_DEVICE_IDENTIFIER, ifModifiedSince,true); 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/DeviceAccessAuthorizationService.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/DeviceAccessAuthorizationService.java index 713defbcee3..c1d4d50b3f6 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/authorization/DeviceAccessAuthorizationService.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/DeviceAccessAuthorizationService.java @@ -28,15 +28,6 @@ import java.util.List; * accessing the device information and performing MDM operations on devices. */ public interface DeviceAccessAuthorizationService { - /** - * This method will check whether the currently logged-in user has the access to the device identified by the given - * DeviceIdentifier. - * - * @param deviceIdentifier - DeviceIdentifier of the device to be checked. - * @return Boolean authorization result. - * @throws DeviceAccessAuthorizationException if something goes wrong when checking the authorization. - */ - boolean isUserAuthorized(DeviceIdentifier deviceIdentifier) throws DeviceAccessAuthorizationException; /** * This method will check whether the currently logged-in user has the access to the device identified by the given @@ -50,18 +41,6 @@ public interface DeviceAccessAuthorizationService { boolean isUserAuthorized(DeviceIdentifier deviceIdentifier, String[] groupPermissions) throws DeviceAccessAuthorizationException; - /** - * This method will check whether the currently logged-in user has the access to the devices identified by the given - * DeviceIdentifier list. - * - * @param deviceIdentifiers - List of DeviceIdentifiers to be checked for authorization. - * @return DeviceAuthorizationResult - Authorization result object including the list of authorized devices and - * unauthorized devices. - * @throws DeviceAccessAuthorizationException if something goes wrong when checking the authorization. - */ - DeviceAuthorizationResult isUserAuthorized(List deviceIdentifiers) throws - DeviceAccessAuthorizationException; - /** * This method will check whether the currently logged-in user has the access to the devices identified by the given * DeviceIdentifier list. @@ -103,18 +82,6 @@ public interface DeviceAccessAuthorizationService { String[] groupPermissions) throws DeviceAccessAuthorizationException; - /** - * This method will check whether the given user has the access to the device identified by the given - * DeviceIdentifier. - * - * @param deviceIdentifier - DeviceIdentifier of the device to be checked. - * @param username - Username of the user to be checked for authorization. - * @return Boolean authorization result. - * @throws DeviceAccessAuthorizationException if something goes wrong when checking the authorization. - */ - boolean isUserAuthorized(DeviceIdentifier deviceIdentifier, String username) throws - DeviceAccessAuthorizationException; - /** * This method will check whether the authenticated user has the admin permissions. * @@ -122,17 +89,4 @@ public interface DeviceAccessAuthorizationService { * @throws DeviceAccessAuthorizationException if something goes wrong when checking the authorization. */ boolean isDeviceAdminUser() throws DeviceAccessAuthorizationException; - - /** - * This method will check whether the given user has the access to the devices identified by the given - * DeviceIdentifier list. - * - * @param deviceIdentifiers - List of DeviceIdentifiers to be checked for authorization. - * @param username - Username of the user to be checked for authorization. - * @return DeviceAuthorizationResult - Authorization result object including the list of authorized devices and - * unauthorized devices. - * @throws DeviceAccessAuthorizationException if something goes wrong when checking the authorization. - */ - DeviceAuthorizationResult isUserAuthorized(List deviceIdentifiers, String username) throws - DeviceAccessAuthorizationException; } \ No newline at end of file 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/DeviceAuthorizationRequest.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/DeviceAuthorizationRequest.java new file mode 100644 index 00000000000..92602fe5f4b --- /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/DeviceAuthorizationRequest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.device.mgt.common.authorization; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.List; + +@ApiModel(value = "DeviceAuthorizationRequest", description = "") +public class DeviceAuthorizationRequest { + + @ApiModelProperty(name = "type", value = "device type") + private String type; + @ApiModelProperty(name = "deviceIds", value = "list of device ids") + private List deviceIds; + @ApiModelProperty(name = "username", value = "user who is accessing the device") + private String username; + @ApiModelProperty(name = "permissions", value = "list of permissions") + private List permissions; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getDeviceIds() { + return deviceIds; + } + + public void setDeviceIds(List deviceIds) { + this.deviceIds = deviceIds; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public List getPermissions() { + return permissions; + } + + public void setPermissions(List permissions) { + this.permissions = 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/GroupAccessAuthorizationException.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/GroupAccessAuthorizationException.java new file mode 100644 index 00000000000..22ab4eef621 --- /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/GroupAccessAuthorizationException.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.device.mgt.common.authorization; + +/** + * Custom exception class which wraps exceptions occurred inside GroupAccessAuthorization service. + */ +public class GroupAccessAuthorizationException extends Exception { + + private static final long serialVersionUID = -3151279331929070297L; + + private String errorMessage; + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public GroupAccessAuthorizationException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public GroupAccessAuthorizationException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public GroupAccessAuthorizationException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public GroupAccessAuthorizationException() { + super(); + } + + public GroupAccessAuthorizationException(Throwable cause) { + super(cause); + } + +} 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 00000000000..15e1079fcf1 --- /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,16 @@ +package io.entgra.device.mgt.core.device.mgt.common.authorization; + +import java.util.List; + +public interface GroupAccessAuthorizationService { + + public boolean isUserAuthorized(int groupId, String username, String[] groupPermissions) + throws GroupAccessAuthorizationException; + + public boolean isUserAuthorized(int groupId, String[] groupPermissions) + throws GroupAccessAuthorizationException; + + public GroupAuthorizationResult isUserAuthorized(List groupIds, String username, String[] groupPermission) + throws GroupAccessAuthorizationException; + +} 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/GroupAuthorizationRequest.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/GroupAuthorizationRequest.java new file mode 100644 index 00000000000..9cda89c5914 --- /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/GroupAuthorizationRequest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.device.mgt.common.authorization; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.List; + +@ApiModel(value = "GroupAuthorizationRequest", description = "") +public class GroupAuthorizationRequest { + + @ApiModelProperty(name = "groupIds", value = "list of group Ids") + private List groupIds; + @ApiModelProperty(name = "username", value = "user who is accessing the device") + private String username; + @ApiModelProperty(name = "permissions", value = "list of permissions") + private List permissions; + + public List getGroupIds() { + return groupIds; + } + + public void setGroupIds(List groupIds) { + this.groupIds = groupIds; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public List getPermissions() { + return permissions; + } + + public void setPermissions(List permissions) { + this.permissions = 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/GroupAuthorizationResult.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/GroupAuthorizationResult.java new file mode 100644 index 00000000000..93608510adf --- /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/GroupAuthorizationResult.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.device.mgt.common.authorization; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a GroupAuthorizationResult including a list of authorized groups and a list of unauthorized groups. + */ +public class GroupAuthorizationResult { + + private List authorizedGroupIds = new ArrayList<>(); + private List unauthorizedGroupIds= new ArrayList<>(); + + public List getAuthorizedGroupIds() { + return authorizedGroupIds; + } + + public void setAuthorizedGroupIds(List authorizedGroupIds) { + this.authorizedGroupIds = authorizedGroupIds; + } + + public List getUnauthorizedGroupIds() { + return unauthorizedGroupIds; + } + + public void setUnauthorizedGroupIds(List unauthorizedGroupIds) { + this.unauthorizedGroupIds = unauthorizedGroupIds; + } + + public void addAuthorizedGroupId(int groupId) { + this.authorizedGroupIds.add(groupId); + } + + public void addUnauthorizedGroupId(int groupId) { + this.unauthorizedGroupIds.add(groupId); + } + +} 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 287b794c4c3..25120a07e0e 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,41 +63,55 @@ 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); - } - } - - private boolean isSharedViaGroup(DeviceIdentifier deviceIdentifier, String username) - throws GroupManagementException, UserStoreException { - List groupsWithDevice = DeviceManagementDataHolder.getInstance() - .getGroupManagementProviderService().getGroups(deviceIdentifier, false); - String[] userRoles = DeviceManagementDataHolder.getInstance().getRealmService() - .getTenantUserRealm(getTenantId()).getUserStoreManager().getRoleListOfUser(username); - for (DeviceGroup deviceGroup : groupsWithDevice) { - List sharingRoles = DeviceManagementDataHolder.getInstance() - .getGroupManagementProviderService().getRoles(deviceGroup.getGroupId()); - for (String role : userRoles) { - if (sharingRoles.contains(role)) { - return true; + if (groupPermissions == null || groupPermissions.length == 0) { + return false; + } 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); } } - return false; } - @Override - public boolean isUserAuthorized(DeviceIdentifier deviceIdentifier, String username) + + private boolean isAuthorizedViaSharedGroup(DeviceIdentifier deviceIdentifier, String username, String groupPermission) throws DeviceAccessAuthorizationException { - return isUserAuthorized(deviceIdentifier, username, null); + 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 @@ -106,18 +120,13 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori return isUserAuthorized(deviceIdentifier, this.getUserName(), groupPermissions); } - @Override - public boolean isUserAuthorized(DeviceIdentifier deviceIdentifier) throws DeviceAccessAuthorizationException { - return isUserAuthorized(deviceIdentifier, this.getUserName(), null); - } - @Override public boolean isDeviceAdminUser() throws DeviceAccessAuthorizationException { 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 +141,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 +158,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 +169,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); @@ -170,55 +179,12 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori return deviceAuthorizationResult; } - @Override - public DeviceAuthorizationResult isUserAuthorized(List deviceIdentifiers, String username) - throws DeviceAccessAuthorizationException { - return isUserAuthorized(deviceIdentifiers, username, null); - } - - @Override - public DeviceAuthorizationResult isUserAuthorized(List deviceIdentifiers) - throws DeviceAccessAuthorizationException { - return isUserAuthorized(deviceIdentifiers, this.getUserName(), null); - } - @Override public DeviceAuthorizationResult isUserAuthorized(List deviceIdentifiers, String[] groupPermissions) throws DeviceAccessAuthorizationException { 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 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 { //Check for device ownership. If the user is the owner of the device we allow the access. @@ -232,15 +198,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 00000000000..acceb466c19 --- /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,173 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.device.mgt.core.authorization; + +import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAccessAuthorizationException; +import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAccessAuthorizationService; +import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAuthorizationResult; +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.opensaml.xmlsec.signature.G; +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 javax.persistence.criteria.CriteriaBuilder; +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 GroupAccessAuthorizationException { + 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; + } + + //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 GroupAccessAuthorizationException("Unable to authorize the access to group : " + + groupId + " for the user : " + + username, e); + } + } + } + + @Override + public GroupAuthorizationResult isUserAuthorized(List groupIds, String username, String[] groupPermission) + throws GroupAccessAuthorizationException { + GroupAuthorizationResult result = new GroupAuthorizationResult(); + for (Integer groupId : groupIds) { + if (isUserAuthorized(groupId, username, groupPermission)) { + result.addAuthorizedGroupId(groupId); + } else { + result.addUnauthorizedGroupId(groupId); + } + } + return result; + } + + + @Override + public boolean isUserAuthorized(int groupId, String[] groupPermissions) + throws GroupAccessAuthorizationException { + return isUserAuthorized(groupId, this.getUserName(), groupPermissions); + } + + private boolean isGroupOwner(int groupId, String username) + throws GroupAccessAuthorizationException { + //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 GroupAccessAuthorizationException("Unable to authorize the access to group : " + + groupId + " for the user : " + + username, e); + } + } + + private boolean isGroupAdminUser(String username, int tenantId) throws GroupAccessAuthorizationException { + 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 GroupAccessAuthorizationException("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/device/details/mgt/impl/DeviceInformationManagerImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/device/details/mgt/impl/DeviceInformationManagerImpl.java index d3681a43c41..e8a8fa6e891 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/device/details/mgt/impl/DeviceInformationManagerImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/device/details/mgt/impl/DeviceInformationManagerImpl.java @@ -18,6 +18,7 @@ package io.entgra.device.mgt.core.device.mgt.core.device.details.mgt.impl; +import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -235,10 +236,12 @@ public class DeviceInformationManagerImpl implements DeviceInformationManager { String username = CarbonContext.getThreadLocalCarbonContext().getUsername(); if (StringUtils.isEmpty(username)) { + String requiredPermission = PermissionManagerServiceImpl.getInstance().getRequiredPermission(); + String[] requiredPermissions = new String[] {requiredPermission}; boolean isUserAuthorized = DeviceManagementDataHolder.getInstance(). getDeviceAccessAuthorizationService().isUserAuthorized( new DeviceIdentifier(device.getDeviceIdentifier(), device.getType()), - device.getEnrolmentInfo().getOwner() + device.getEnrolmentInfo().getOwner(), requiredPermissions ); if (isUserAuthorized) { username = device.getEnrolmentInfo().getOwner(); 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 67368744877..48d573a5fa6 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 b3bc1f2f0de..b2e1529f40a 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); 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/operation/mgt/OperationManagerImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/OperationManagerImpl.java index c7a86bfb825..049cae776e5 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/OperationManagerImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/OperationManagerImpl.java @@ -19,6 +19,7 @@ package io.entgra.device.mgt.core.device.mgt.core.operation.mgt; import com.google.gson.Gson; +import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; import io.entgra.device.mgt.core.device.mgt.extensions.logger.spi.EntgraLogger; import io.entgra.device.mgt.core.notification.logger.DeviceConnectivityLogContext; import io.entgra.device.mgt.core.notification.logger.impl.EntgraDeviceConnectivityLoggerImpl; @@ -561,9 +562,11 @@ public class OperationManagerImpl implements OperationManager { } else { boolean isAuthorized; authorizedDeviceList = new ArrayList<>(); + String requiredPermission = PermissionManagerServiceImpl.getInstance().getRequiredPermission(); + String[] requiredPermissions = new String[] {requiredPermission}; for (DeviceIdentifier devId : deviceIds) { isAuthorized = DeviceManagementDataHolder.getInstance().getDeviceAccessAuthorizationService(). - isUserAuthorized(devId); + isUserAuthorized(devId, requiredPermissions); if (isAuthorized) { authorizedDeviceList.add(devId); } else { @@ -1470,9 +1473,11 @@ public class OperationManagerImpl implements OperationManager { int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); String user = this.getUser(); boolean isUserAuthorized; + String requiredPermission = PermissionManagerServiceImpl.getInstance().getRequiredPermission(); + String[] requiredPermissions = new String[] {requiredPermission}; try { isUserAuthorized = DeviceManagementDataHolder.getInstance() - .getDeviceAccessAuthorizationService().isUserAuthorized(deviceId, user); + .getDeviceAccessAuthorizationService().isUserAuthorized(deviceId, user, requiredPermissions); } catch (DeviceAccessAuthorizationException e) { throw new OperationManagementException("Error occurred while checking the device access permissions for '" + deviceId.getType() + "' device carrying the identifier '" + 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/permission/mgt/PermissionManagerServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/permission/mgt/PermissionManagerServiceImpl.java index 7de2a3a9c90..8b7c9244adc 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/permission/mgt/PermissionManagerServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/permission/mgt/PermissionManagerServiceImpl.java @@ -32,6 +32,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerService { private static PermissionManagerServiceImpl registryBasedPermissionManager; private static APIResourcePermissions apiResourcePermissions; + private ThreadLocal requiredPermission = null; private PermissionManagerServiceImpl() { } @@ -64,4 +65,16 @@ public class PermissionManagerServiceImpl implements PermissionManagerService { public List getPermission(String context) throws PermissionManagementException { return apiResourcePermissions.getPermissions(context); } + + public String getRequiredPermission() { + if (requiredPermission == null) { + requiredPermission = new ThreadLocal<>(); + } + return requiredPermission.get(); + } + + public void setRequiredPermission(String permission) { + requiredPermission = new ThreadLocal<>(); + requiredPermission.set(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/service/GroupManagementProviderServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/GroupManagementProviderServiceImpl.java index 0941d3d3a1c..88aad71dcdf 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/GroupManagementProviderServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/GroupManagementProviderServiceImpl.java @@ -32,6 +32,7 @@ import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.core.dao.GroupDAO; import io.entgra.device.mgt.core.device.mgt.core.dao.GroupManagementDAOException; import io.entgra.device.mgt.core.device.mgt.core.dao.GroupManagementDAOFactory; +import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -593,10 +594,24 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid } else { List allDeviceGroupIdsOfUser = getGroupIds(username); rootGroups = this.getGroups(allDeviceGroupIdsOfUser, tenantId); - if (requireGroupProps) { + try { + GroupManagementDAOFactory.openConnection(); for (DeviceGroup rootGroup : rootGroups) { - populateGroupProperties(rootGroup, tenantId); + parentPath = DeviceManagerUtil.createParentPath(rootGroup); + childrenGroups = groupDAO.getChildrenGroups(parentPath, tenantId); + createGroupWithChildren( + rootGroup, childrenGroups, requireGroupProps, tenantId, request.getDepth(), 0); + if (requireGroupProps) { + populateGroupProperties(rootGroup, tenantId); + } } + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the data source to retrieve all groups " + + "with hierarchy when username is provided"; + log.error(msg, e); + throw new GroupManagementException(msg, e); + } finally { + GroupManagementDAOFactory.closeConnection(); } } } catch (GroupManagementDAOException e) { diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/authorization/DeviceAccessAuthorizationServiceTest.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/authorization/DeviceAccessAuthorizationServiceTest.java index 6565a4b029d..0e31232a03a 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/authorization/DeviceAccessAuthorizationServiceTest.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/authorization/DeviceAccessAuthorizationServiceTest.java @@ -193,7 +193,7 @@ public class DeviceAccessAuthorizationServiceTest { public void userAuthDevIdUserName() throws Exception { PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(ADMIN_USER); for (DeviceIdentifier deviceId : deviceIds) { - Assert.assertTrue(deviceAccessAuthorizationService.isUserAuthorized(deviceId, ADMIN_USER), + Assert.assertTrue(deviceAccessAuthorizationService.isUserAuthorized(deviceId, ADMIN_USER, new String[]{NON_ADMIN_PERMISSION}), "Device access authorization for admin user failed"); } } @@ -202,7 +202,7 @@ public class DeviceAccessAuthorizationServiceTest { public void userAuthDevIdUserNameResult() throws DeviceAccessAuthorizationException { PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(ADMIN_USER); DeviceAuthorizationResult deviceAuthorizationResult = deviceAccessAuthorizationService. - isUserAuthorized(deviceIds, ADMIN_USER); + isUserAuthorized(deviceIds, ADMIN_USER, new String[]{NON_ADMIN_PERMISSION}); Assert.assertEquals(deviceAuthorizationResult.getAuthorizedDevices().size(), 5, "Expected 5 authorized devices for admin user"); Assert.assertEquals(deviceAuthorizationResult.getUnauthorizedDevices().size(), 0, @@ -213,7 +213,7 @@ public class DeviceAccessAuthorizationServiceTest { public void userAuthDevId() throws Exception { PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(ADMIN_USER); for (DeviceIdentifier deviceId : deviceIds) { - Assert.assertTrue(deviceAccessAuthorizationService.isUserAuthorized(deviceId), + Assert.assertTrue(deviceAccessAuthorizationService.isUserAuthorized(deviceId, new String[]{NON_ADMIN_PERMISSION}), "Authorize user from device identifier failed"); } } @@ -222,7 +222,7 @@ public class DeviceAccessAuthorizationServiceTest { public void userAuthDevIdResult() throws Exception { PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(ADMIN_USER); DeviceAuthorizationResult deviceAuthorizationResult = deviceAccessAuthorizationService. - isUserAuthorized(deviceIds); + isUserAuthorized(deviceIds, new String[]{NON_ADMIN_PERMISSION}); Assert.assertEquals(deviceAuthorizationResult.getAuthorizedDevices().size(), 5, "Expected 5 authorized devices for admin user"); Assert.assertEquals(deviceAuthorizationResult.getUnauthorizedDevices().size(), 0, diff --git a/components/webapp-authenticator-framework/io.entgra.device.mgt.core.webapp.authenticator.framework/src/main/java/io/entgra/device/mgt/core/webapp/authenticator/framework/authorizer/PermissionAuthorizer.java b/components/webapp-authenticator-framework/io.entgra.device.mgt.core.webapp.authenticator.framework/src/main/java/io/entgra/device/mgt/core/webapp/authenticator/framework/authorizer/PermissionAuthorizer.java index 0d509200e4f..aed1ecf8363 100644 --- a/components/webapp-authenticator-framework/io.entgra.device.mgt.core.webapp.authenticator.framework/src/main/java/io/entgra/device/mgt/core/webapp/authenticator/framework/authorizer/PermissionAuthorizer.java +++ b/components/webapp-authenticator-framework/io.entgra.device.mgt.core.webapp.authenticator.framework/src/main/java/io/entgra/device/mgt/core/webapp/authenticator/framework/authorizer/PermissionAuthorizer.java @@ -134,6 +134,7 @@ public class PermissionAuthorizer { } if (isUserAuthorized) { + PermissionManagerServiceImpl.getInstance().setRequiredPermission(requiredPermission); return WebappAuthenticator.Status.SUCCESS; } else { return WebappAuthenticator.Status.FAILURE;