Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,14 @@ public SCIMRoleManager(RoleManagementService roleManagementService, String tenan
}

@Override
public Role createRole(Role role) throws CharonException, ConflictException, BadRequestException {
public Role createRole(Role role) throws CharonException, ConflictException,
BadRequestException, ForbiddenException {

if (SCIMCommonUtils.isBulkRequest()) {
SCIMCommonUtils.validateAuthorizedScopes(Arrays.asList(
"internal_bulk_resource_create", "internal_bulk_role_create",
"internal_org_bulk_resource_create", "internal_org_bulk_role_create"));
}

if (log.isDebugEnabled()) {
log.debug("Creating role: " + role.getDisplayName());
Expand Down Expand Up @@ -188,7 +195,14 @@ public Role getRole(String roleID, Map<String, Boolean> requiredAttributes)
}

@Override
public void deleteRole(String roleID) throws CharonException, NotFoundException, BadRequestException {
public void deleteRole(String roleID) throws CharonException, NotFoundException,
BadRequestException, ForbiddenException{

if (SCIMCommonUtils.isBulkRequest()) {
SCIMCommonUtils.validateAuthorizedScopes(Arrays.asList(
"internal_bulk_resource_create", "internal_bulk_role_delete",
"internal_org_bulk_resource_create", "internal_org_bulk_role_delete"));
}

try {
roleManagementService.deleteRole(roleID, tenantDomain);
Expand Down Expand Up @@ -373,7 +387,13 @@ private List<Role> getScimRolesList(List<RoleBasicInfo> roles) throws BadRequest

@Override
public Role updateRole(Role oldRole, Role newRole)
throws BadRequestException, CharonException, ConflictException, NotFoundException {
throws BadRequestException, CharonException, ConflictException, NotFoundException, ForbiddenException {

if (SCIMCommonUtils.isBulkRequest()) {
SCIMCommonUtils.validateAuthorizedScopes(Arrays.asList(
"internal_bulk_resource_create", "internal_bulk_role_update",
"internal_org_bulk_resource_create", "internal_org_bulk_role_update"));
}

doUpdateRoleName(oldRole, newRole);
doUpdateUsers(oldRole, newRole);
Expand Down Expand Up @@ -555,6 +575,12 @@ public RolesGetResponse listRolesWithPost(SearchRequest searchRequest)
public Role patchRole(String roleId, Map<String, List<PatchOperation>> patchOperations)
throws BadRequestException, CharonException, ConflictException, NotFoundException, ForbiddenException {

if (SCIMCommonUtils.isBulkRequest()) {
SCIMCommonUtils.validateAuthorizedScopes(Arrays.asList(
"internal_bulk_resource_create", "internal_bulk_role_update",
"internal_org_bulk_resource_create", "internal_org_bulk_role_update"));
}

String currentRoleName = getCurrentRoleName(roleId, tenantDomain);

if (log.isDebugEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,14 @@ public SCIMRoleManagerV2(RoleManagementService roleManagementService, String ten
}

public RoleV2 createRole(RoleV2 role)
throws CharonException, ConflictException, NotImplementedException, BadRequestException {
throws CharonException, ConflictException, NotImplementedException,
BadRequestException, ForbiddenException {

if (SCIMCommonUtils.isBulkRequest()) {
SCIMCommonUtils.validateAuthorizedScopes(Arrays.asList(
"internal_bulk_resource_create", "internal_bulk_role_create",
"internal_org_bulk_resource_create", "internal_org_bulk_role_create"));
Comment on lines +129 to +131

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get these from resource access control file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check kernel

}

try {
// Check if the role already exists.
Expand Down Expand Up @@ -356,7 +363,14 @@ private List<MultiValuedComplexType> convertRolePropertiesToMultiValuedComplexTy
return rolePropertyValues;
}

public void deleteRole(String roleID) throws CharonException, NotFoundException, BadRequestException {
public void deleteRole(String roleID) throws CharonException, NotFoundException,
BadRequestException, ForbiddenException {

if (SCIMCommonUtils.isBulkRequest()) {
SCIMCommonUtils.validateAuthorizedScopes(Arrays.asList(
"internal_bulk_resource_create", "internal_bulk_role_delete",
"internal_org_bulk_resource_create", "internal_org_bulk_role_delete"));
}

try {
if (isSharedRole(roleID)) {
Expand Down Expand Up @@ -401,7 +415,13 @@ public RolesV2GetResponse listRolesWithPost(SearchRequest searchRequest, List<St

@Override
public RoleV2 updateRole(RoleV2 oldRole, RoleV2 newRole)
throws BadRequestException, CharonException, ConflictException, NotFoundException {
throws BadRequestException, CharonException, ConflictException, NotFoundException, ForbiddenException {

if (SCIMCommonUtils.isBulkRequest()) {
SCIMCommonUtils.validateAuthorizedScopes(Arrays.asList(
"internal_bulk_resource_create", "internal_bulk_role_update",
"internal_org_bulk_resource_create", "internal_org_bulk_role_update"));
}

doUpdateRoleName(oldRole, newRole);
doUpdateUsers(oldRole, newRole);
Expand All @@ -421,6 +441,12 @@ public RoleV2 updateRole(RoleV2 oldRole, RoleV2 newRole)
public RoleV2 patchRole(String roleId, Map<String, List<PatchOperation>> patchOperations)
throws BadRequestException, CharonException, ConflictException, NotFoundException, ForbiddenException {

if (SCIMCommonUtils.isBulkRequest()) {
SCIMCommonUtils.validateAuthorizedScopes(Arrays.asList(
"internal_bulk_resource_create", "internal_bulk_role_update",
"internal_org_bulk_resource_create", "internal_org_bulk_role_update"));
}

String currentRoleName = getCurrentRoleName(roleId, tenantDomain);
if (LOG.isDebugEnabled()) {
LOG.debug("Updating Role: " + roleId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,12 @@ public SCIMUserManager(UserStoreManager carbonUserStoreManager,
public User createUser(User user, Map<String, Boolean> requiredAttributes)
throws CharonException, ConflictException, BadRequestException, ForbiddenException {

if (SCIMCommonUtils.isBulkRequest()) {
SCIMCommonUtils.validateAuthorizedScopes(Arrays.asList("internal_bulk_user_create",
"internal_bulk_resource_create", "internal_org_bulk_user_create",
"internal_org_bulk_resource_create"));
}

String userStoreName = null;
try {
String userStoreDomainFromSP = getUserStoreDomainFromSP();
Expand Down Expand Up @@ -3643,22 +3649,24 @@ public void updateGroup(Group oldGroup, Group newGroup) throws CharonException,

@Override
public void patchGroup(String groupId, String currentGroupName, Map<String, List<PatchOperation>> patchOperations)
throws NotImplementedException, BadRequestException, CharonException, NotFoundException {
throws NotImplementedException, BadRequestException, CharonException,
NotFoundException, ForbiddenException {

doPatchGroup(groupId, currentGroupName, patchOperations);
}

@Override
public Group patchGroup(String groupId, String currentGroupName, Map<String, List<PatchOperation>> patchOperations,
Map<String, Boolean> requiredAttributes) throws NotImplementedException,
BadRequestException, CharonException, NotFoundException {
BadRequestException, CharonException, NotFoundException, ForbiddenException {

doPatchGroup(groupId, currentGroupName, patchOperations);
return getGroup(groupId, requiredAttributes);
}

private void doPatchGroup(String groupId, String currentGroupName, Map<String, List<PatchOperation>> patchOperations) throws
NotImplementedException, BadRequestException, CharonException, NotFoundException {
NotImplementedException, BadRequestException, CharonException, NotFoundException,
ForbiddenException {

if (log.isDebugEnabled()) {
log.debug("Updating group: " + currentGroupName);
Expand Down Expand Up @@ -3692,6 +3700,14 @@ private void doPatchGroup(String groupId, String currentGroupName, Map<String, L
Set<Object> newlyAddedMemberIds = new HashSet<>();
Set<Object> deletedMemberIds = new HashSet<>();

if (CollectionUtils.isNotEmpty(memberOperations)){
if (SCIMCommonUtils.isBulkRequest()) {
SCIMCommonUtils.validateAuthorizedScopes(Arrays.asList("internal_bulk_resource_create",
"internal_bulk_group_update", "internal_org_bulk_resource_create",
"internal_org_bulk_group_update"));
}
}

for (PatchOperation memberOperation : memberOperations) {
if (memberOperation.getValues() instanceof Map) {
Map<String, String> memberObject = (Map<String, String>) memberOperation.getValues();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public class SCIMCommonConstants {
public static final String SERVICE_PROVIDER_CONFIG = "/ServiceProviderConfig";
public static final String RESOURCE_TYPE = "/ResourceTypes";
public static final String DEFAULT = "default";
public static final String AUTHORIZED_SCOPES = "authorizedScopes";
public static final String NORMALIZED_REQUEST_URI = "normalizedRequestURI";
public static final String BULK_ENDPOINT = "/scim2/Bulk";

public static final int USER = 1;
public static final int GROUP = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.wso2.charon3.core.config.SCIMSystemSchemaExtensionBuilder;
import org.wso2.charon3.core.config.SCIMUserSchemaExtensionBuilder;
import org.wso2.charon3.core.exceptions.CharonException;
import org.wso2.charon3.core.exceptions.ForbiddenException;
import org.wso2.charon3.core.exceptions.InternalErrorException;
import org.wso2.charon3.core.schema.AttributeSchema;
import org.wso2.charon3.core.schema.SCIMConstants;
Expand Down Expand Up @@ -1072,4 +1073,28 @@ public static boolean isConsiderServerWideUserEndpointMaxLimitEnabled() {
}
return Boolean.parseBoolean(considerServerWideUserEndpointMaxLimitProperty);
}

public static boolean isBulkRequest() {

if (IdentityUtil.threadLocalProperties.get().get(SCIMCommonConstants.NORMALIZED_REQUEST_URI) != null) {
return IdentityUtil.threadLocalProperties.get()
.get(SCIMCommonConstants.NORMALIZED_REQUEST_URI).toString()
.contains(SCIMCommonConstants.BULK_ENDPOINT);
}

return false;
}

public static void validateAuthorizedScopes(List<String> requiredScopes)
throws ForbiddenException {

List<String> authorizedScopes = (List<String>) IdentityUtil.threadLocalProperties.get().get(
SCIMCommonConstants.AUTHORIZED_SCOPES);

if (authorizedScopes != null &&
requiredScopes.stream().noneMatch(authorizedScopes::contains)) {
throw new ForbiddenException(
"Operation is not permitted. You do not have permissions to make this request.");
}
}
Comment on lines +1091 to +1099

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this to get the scopes from privileged carbon context.

Comment on lines +1088 to +1099

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think about moving this to a separate interception layer.

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.wso2.charon3.core.exceptions.BadRequestException;
import org.wso2.charon3.core.exceptions.CharonException;
import org.wso2.charon3.core.exceptions.ConflictException;
import org.wso2.charon3.core.exceptions.ForbiddenException;
import org.wso2.charon3.core.exceptions.NotFoundException;
import org.wso2.charon3.core.exceptions.NotImplementedException;
import org.wso2.charon3.core.objects.Group;
Expand Down Expand Up @@ -236,7 +237,7 @@ public Object[][] dataProviderForCreateRolePositive() {
@Test(dataProvider = "dataProviderForCreateRolePositive")
public void testCreateRolePositive(String roleId, String roleDisplayName, String tenantDomain)
throws IdentityRoleManagementException, BadRequestException, CharonException, ConflictException,
OrganizationManagementException {
OrganizationManagementException, ForbiddenException {

Role role = getDummyRole(roleId, roleDisplayName);
when(mockRoleManagementService.addRole(nullable(String.class), anyList(), anyList(),
Expand Down Expand Up @@ -388,7 +389,8 @@ public Object[][] dataProviderForDeleteRolePositive() {

@Test(dataProvider = "dataProviderForDeleteRolePositive")
public void testDeleteRolePositive(String roleId, String tenantDomain)
throws IdentityRoleManagementException, NotFoundException, BadRequestException, CharonException {
throws IdentityRoleManagementException, NotFoundException, BadRequestException,
CharonException, ForbiddenException {

doNothing().when(mockRoleManagementService).deleteRole(roleId, tenantDomain);
SCIMRoleManager roleManager = new SCIMRoleManager(mockRoleManagementService, tenantDomain);
Expand Down Expand Up @@ -648,7 +650,7 @@ public Object[][] dataProviderForUpdateRoleUpdateRoleName() {
public void testUpdateRoleUpdateRoleName(String roleId, String oldRoleName, String newRoleName, String tenantDomain,
String type)
throws IdentityRoleManagementException, BadRequestException, CharonException, ConflictException,
NotFoundException {
NotFoundException, ForbiddenException {

RoleBasicInfo roleBasicInfo = new RoleBasicInfo(roleId, newRoleName);
Role[] oldAndNewRoles = getOldAndNewRoleDummies(roleId, oldRoleName, newRoleName, type);
Expand Down Expand Up @@ -714,7 +716,7 @@ public Object[][] dataProviderForUpdateRoleUpdateRoleNameThrowingErrors() {
public void testUpdateRoleUpdateRoleNameThrowingErrors(String roleId, String oldRoleName, String newRoleName,
String tenantDomain, String sError)
throws IdentityRoleManagementException, BadRequestException, CharonException, ConflictException,
NotFoundException {
NotFoundException, ForbiddenException {

Role[] oldAndNewRoles = getOldAndNewRoleDummies(roleId, oldRoleName, newRoleName);

Expand Down Expand Up @@ -767,7 +769,7 @@ public Object[][] dataProviderForUpdateRoleUpdateUserListOfRoleThrowingErrors()
public void testUpdateRoleUpdateUserListOfRoleThrowingErrors(String roleId, String oldRoleName, String newRoleName,
String tenantDomain, String type, String sError)
throws IdentityRoleManagementException, BadRequestException, CharonException, ConflictException,
NotFoundException {
NotFoundException, ForbiddenException {

RoleBasicInfo roleBasicInfo = new RoleBasicInfo(roleId, newRoleName);
Role[] oldAndNewRoles = getOldAndNewRoleDummies(roleId, oldRoleName, newRoleName, type);
Expand Down Expand Up @@ -813,7 +815,7 @@ public Object[][] dataProviderForUpdateRoleUpdateGroupListOfRoleThrowingErrors()
public void testUpdateRoleUpdateGroupListOfRoleThrowingErrors(String roleId, String oldRoleName, String newRoleName,
String tenantDomain, String type, String sError)
throws IdentityRoleManagementException, BadRequestException, CharonException, ConflictException,
NotFoundException {
NotFoundException, ForbiddenException {

RoleBasicInfo roleBasicInfo = new RoleBasicInfo(roleId, newRoleName);
Role[] oldAndNewRoles = getOldAndNewRoleDummies(roleId, oldRoleName, newRoleName, type);
Expand Down Expand Up @@ -860,7 +862,7 @@ public void testRoleUpdatePermissionListOfRoleThrowingErrors(String roleId, Stri
String tenantDomain, String permissionType,
String sError)
throws IdentityRoleManagementException, BadRequestException, CharonException,
ConflictException, NotFoundException {
ConflictException, NotFoundException, ForbiddenException {

RoleBasicInfo roleBasicInfo = new RoleBasicInfo(roleId, newRoleName);
Role[] oldAndNewRoles = getOldAndNewRoleDummies(roleId, oldRoleName, newRoleName, permissionType);
Expand Down
Loading