Skip to content

Commit d00a631

Browse files
committed
check every rule belongs to the project and role when reordering project role permissions
1 parent 376c1b4 commit d00a631

2 files changed

Lines changed: 99 additions & 7 deletions

File tree

‎api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/UpdateProjectRolePermissionCmd.java‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public void execute() {
122122
if (getProjectRulePermissionOrder() != null) {
123123
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Parameters permission and ruleid must be mutually exclusive with ruleorder");
124124
}
125-
ProjectRolePermission rolePermission = getValidProjectRolePermission();
125+
ProjectRolePermission rolePermission = findProjectRolePermissionInProject(getProjectRuleId());
126126
CallContext.current().setEventDetails("Updating project role permission for rule id: " + getProjectRuleId() + " to: " + getProjectRolePermission().toString());
127127
result = projRoleService.updateProjectRolePermission(projectId, projectRole, rolePermission, getProjectRolePermission());
128128
}
@@ -131,20 +131,24 @@ public void execute() {
131131
setResponseObject(response);
132132
}
133133

134-
private ProjectRolePermission getValidProjectRolePermission() {
135-
ProjectRolePermission rolePermission = projRoleService.findProjectRolePermission(getProjectRuleId());
134+
/**
135+
* Resolves a caller supplied rule id and rejects it when it belongs to another project, so that
136+
* no code path can reach permissions outside the project the command was called with.
137+
*/
138+
private ProjectRolePermission findProjectRolePermissionInProject(Long rolePermissionId) {
139+
final ProjectRolePermission rolePermission = projRoleService.findProjectRolePermission(rolePermissionId);
136140
if (rolePermission == null || rolePermission.getProjectId() != getProjectId()) {
137141
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Role permission doesn't exist in the project, probably because of invalid rule id");
138142
}
139143
return rolePermission;
140144
}
141145

142-
private boolean updateProjectRolePermissionOrder(ProjectRole projectRole) {
146+
protected boolean updateProjectRolePermissionOrder(ProjectRole projectRole) {
143147
final List<ProjectRolePermission> rolePermissionsOrder = new ArrayList<>();
144148
for (Long rolePermissionId : getProjectRulePermissionOrder()) {
145-
final ProjectRolePermission rolePermission = projRoleService.findProjectRolePermission(rolePermissionId);
146-
if (rolePermission == null) {
147-
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Provided project role permission(s) do not exist");
149+
final ProjectRolePermission rolePermission = findProjectRolePermissionInProject(rolePermissionId);
150+
if (rolePermission.getProjectRoleId() != projectRole.getId()) {
151+
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Provided project role permission(s) do not belong to the given project role");
148152
}
149153
rolePermissionsOrder.add(rolePermission);
150154
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.api.command.admin.acl.project;
18+
19+
import org.apache.cloudstack.acl.ProjectRole;
20+
import org.apache.cloudstack.acl.ProjectRolePermission;
21+
import org.apache.cloudstack.acl.ProjectRoleService;
22+
import org.apache.cloudstack.api.ServerApiException;
23+
import org.junit.Before;
24+
import org.junit.Test;
25+
import org.mockito.Mock;
26+
import org.mockito.Mockito;
27+
import org.mockito.MockitoAnnotations;
28+
import org.springframework.test.util.ReflectionTestUtils;
29+
30+
import java.util.Arrays;
31+
32+
public class UpdateProjectRolePermissionCmdTest {
33+
34+
@Mock
35+
private ProjectRoleService projectRoleService;
36+
@Mock
37+
private ProjectRole projectRole;
38+
@Mock
39+
private ProjectRolePermission projectRolePermissionOne;
40+
@Mock
41+
private ProjectRolePermission projectRolePermissionTwo;
42+
43+
private final UpdateProjectRolePermissionCmd updateProjectRolePermissionCmd = new UpdateProjectRolePermissionCmd();
44+
45+
private static final Long projectId = 9L;
46+
private static final Long ruleOneId = 111L;
47+
private static final Long ruleTwoId = 222L;
48+
private static final Long projectRoleId = 20L;
49+
50+
@Before
51+
public void setUp() throws Exception {
52+
MockitoAnnotations.initMocks(this);
53+
updateProjectRolePermissionCmd.projRoleService = projectRoleService;
54+
55+
Mockito.when(projectRolePermissionOne.getProjectId()).thenReturn(projectId);
56+
Mockito.when(projectRolePermissionTwo.getProjectId()).thenReturn(projectId);
57+
Mockito.when(projectRolePermissionOne.getProjectRoleId()).thenReturn(projectRoleId);
58+
Mockito.when(projectRolePermissionTwo.getProjectRoleId()).thenReturn(projectRoleId);
59+
Mockito.when(projectRole.getId()).thenReturn(projectRoleId);
60+
61+
ReflectionTestUtils.setField(updateProjectRolePermissionCmd, "projectRulePermissionOrder", Arrays.asList(ruleOneId, ruleTwoId));
62+
ReflectionTestUtils.setField(updateProjectRolePermissionCmd, "projectId", projectId);
63+
64+
Mockito.when(projectRoleService.findProjectRolePermission(ruleOneId)).thenReturn(projectRolePermissionOne);
65+
Mockito.when(projectRoleService.findProjectRolePermission(ruleTwoId)).thenReturn(projectRolePermissionTwo);
66+
}
67+
68+
@Test(expected = ServerApiException.class)
69+
public void testUpdateProjectRolePermissionOrderRuleIdFromAnotherProject() {
70+
Long differentProjectId = 2L;
71+
Mockito.when(projectRolePermissionTwo.getProjectId()).thenReturn(differentProjectId);
72+
updateProjectRolePermissionCmd.updateProjectRolePermissionOrder(projectRole);
73+
}
74+
75+
@Test(expected = ServerApiException.class)
76+
public void testUpdateProjectRolePermissionOrderDifferentRuleRoleInSameProject() {
77+
Long differentRoleId = 3L;
78+
Mockito.when(projectRolePermissionTwo.getProjectRoleId()).thenReturn(differentRoleId);
79+
updateProjectRolePermissionCmd.updateProjectRolePermissionOrder(projectRole);
80+
}
81+
82+
@Test
83+
public void testUpdateProjectRolePermissionOrder() {
84+
updateProjectRolePermissionCmd.updateProjectRolePermissionOrder(projectRole);
85+
Mockito.verify(projectRoleService).updateProjectRolePermission(Mockito.eq(projectId), Mockito.eq(projectRole),
86+
Mockito.eq(Arrays.asList(projectRolePermissionOne, projectRolePermissionTwo)));
87+
}
88+
}

0 commit comments

Comments
 (0)