SONAR-7174 Check scan permission per project in /api/ce/task WS

This commit is contained in:
Julien Lancelot 2016-01-08 16:47:30 +01:00
parent 2b99549791
commit bd62851006
2 changed files with 117 additions and 42 deletions

View File

@ -20,12 +20,10 @@
package org.sonar.server.computation.ws;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
import javax.annotation.Nullable;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
@ -35,13 +33,15 @@ import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.WsCe;
import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION;
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
public class TaskAction implements CeWsAction {
public static final String ACTION = "task";
public static final String PARAM_TASK_UUID = "id";
private static final Set<String> AUTHORIZED_PERMISSIONS = ImmutableSet.of(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.SYSTEM_ADMIN);
private final DbClient dbClient;
private final TaskFormatter wsTaskFormatter;
@ -71,18 +71,18 @@ public class TaskAction implements CeWsAction {
@Override
public void handle(Request wsRequest, Response wsResponse) throws Exception {
userSession.checkAnyPermissions(AUTHORIZED_PERMISSIONS);
String taskUuid = wsRequest.mandatoryParam(PARAM_TASK_UUID);
DbSession dbSession = dbClient.openSession(false);
try {
WsCe.TaskResponse.Builder wsTaskResponse = WsCe.TaskResponse.newBuilder();
Optional<CeQueueDto> queueDto = dbClient.ceQueueDao().selectByUuid(dbSession, taskUuid);
if (queueDto.isPresent()) {
checkPermission(queueDto.get().getComponentUuid());
wsTaskResponse.setTask(wsTaskFormatter.formatQueue(dbSession, queueDto.get()));
} else {
Optional<CeActivityDto> activityDto = dbClient.ceActivityDao().selectByUuid(dbSession, taskUuid);
if (activityDto.isPresent()) {
checkPermission(activityDto.get().getComponentUuid());
wsTaskResponse.setTask(wsTaskFormatter.formatActivity(dbSession, activityDto.get()));
} else {
throw new NotFoundException();
@ -94,4 +94,13 @@ public class TaskAction implements CeWsAction {
dbClient.closeSession(dbSession);
}
}
private void checkPermission(@Nullable String projectUuid) {
if (!userSession.hasPermission(SYSTEM_ADMIN)
&& !userSession.hasPermission(SCAN_EXECUTION)
&& (projectUuid == null || !userSession.hasComponentUuidPermission(SCAN_EXECUTION, projectUuid))
) {
throw insufficientPrivilegesException();
}
}
}

View File

@ -26,7 +26,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.util.Protobuf;
import org.sonar.db.DbTester;
import org.sonar.db.ce.CeActivityDto;
@ -48,13 +47,23 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonar.core.permission.GlobalPermissions.PREVIEW_EXECUTION;
import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION;
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
public class TaskActionTest {
static final ComponentDto PROJECT = ComponentTesting.newProjectDto()
.setUuid("PROJECT_1")
.setName("Project One")
.setKey("P1");
@Rule
public UserSessionRule userSession = UserSessionRule.standalone();
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
@ -65,19 +74,18 @@ public class TaskActionTest {
@Before
public void setUp() {
dbTester.getDbClient().componentDao().insert(dbTester.getSession(), PROJECT);
when(ceLogging.getFile(any(LogFileRef.class))).thenReturn(Optional.<File>absent());
userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
}
@Test
public void task_is_in_queue() throws Exception {
ComponentDto project = ComponentTesting.newProjectDto().setUuid("PROJECT_1").setName("Project One").setKey("P1");
dbTester.getDbClient().componentDao().insert(dbTester.getSession(), project);
userSession.login("john").setGlobalPermissions(SYSTEM_ADMIN);
CeQueueDto queueDto = new CeQueueDto();
queueDto.setTaskType(CeTaskTypes.REPORT);
queueDto.setUuid("TASK_1");
queueDto.setComponentUuid(project.uuid());
queueDto.setComponentUuid(PROJECT.uuid());
queueDto.setStatus(CeQueueDto.Status.PENDING);
queueDto.setSubmitterLogin("john");
dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
@ -92,22 +100,21 @@ public class TaskActionTest {
assertThat(taskResponse.getTask().getId()).isEqualTo("TASK_1");
assertThat(taskResponse.getTask().getStatus()).isEqualTo(WsCe.TaskStatus.PENDING);
assertThat(taskResponse.getTask().getSubmitterLogin()).isEqualTo("john");
assertThat(taskResponse.getTask().getComponentId()).isEqualTo(project.uuid());
assertThat(taskResponse.getTask().getComponentKey()).isEqualTo(project.key());
assertThat(taskResponse.getTask().getComponentName()).isEqualTo(project.name());
assertThat(taskResponse.getTask().getComponentId()).isEqualTo(PROJECT.uuid());
assertThat(taskResponse.getTask().getComponentKey()).isEqualTo(PROJECT.key());
assertThat(taskResponse.getTask().getComponentName()).isEqualTo(PROJECT.name());
assertThat(taskResponse.getTask().hasExecutionTimeMs()).isFalse();
assertThat(taskResponse.getTask().getLogs()).isFalse();
}
@Test
public void task_is_archived() throws Exception {
ComponentDto project = ComponentTesting.newProjectDto().setUuid("PROJECT_1").setName("Project One").setKey("P1");
dbTester.getDbClient().componentDao().insert(dbTester.getSession(), project);
userSession.login("john").setGlobalPermissions(SYSTEM_ADMIN);
CeQueueDto queueDto = new CeQueueDto();
queueDto.setTaskType(CeTaskTypes.REPORT);
queueDto.setUuid("TASK_1");
queueDto.setComponentUuid(project.uuid());
queueDto.setComponentUuid(PROJECT.uuid());
CeActivityDto activityDto = new CeActivityDto(queueDto);
activityDto.setStatus(CeActivityDto.Status.FAILED);
activityDto.setExecutionTimeMs(500L);
@ -124,9 +131,9 @@ public class TaskActionTest {
WsCe.Task task = taskResponse.getTask();
assertThat(task.getId()).isEqualTo("TASK_1");
assertThat(task.getStatus()).isEqualTo(WsCe.TaskStatus.FAILED);
assertThat(task.getComponentId()).isEqualTo(project.uuid());
assertThat(task.getComponentKey()).isEqualTo(project.key());
assertThat(task.getComponentName()).isEqualTo(project.name());
assertThat(task.getComponentId()).isEqualTo(PROJECT.uuid());
assertThat(task.getComponentKey()).isEqualTo(PROJECT.key());
assertThat(task.getComponentName()).isEqualTo(PROJECT.name());
assertThat(task.getAnalysisId()).isEqualTo("123456");
assertThat(task.getExecutionTimeMs()).isEqualTo(500L);
assertThat(task.getLogs()).isFalse();
@ -134,17 +141,18 @@ public class TaskActionTest {
@Test
public void task_not_found() throws Exception {
expectedException.expect(NotFoundException.class);
userSession.login("john").setGlobalPermissions(SYSTEM_ADMIN);
expectedException.expect(NotFoundException.class);
ws.newRequest()
.setParam("id", "DOES_NOT_EXIST")
.execute();
}
@Test
public void fail_if_not_admin_nor_scan_permission() {
expectedException.expect(ForbiddenException.class);
userSession.setGlobalPermissions(GlobalPermissions.PREVIEW_EXECUTION);
public void not_fail_on_queue_task_not_linked_on_project_with_system_admin_permissions() {
userSession.login("john").setGlobalPermissions(SYSTEM_ADMIN);
CeQueueDto queueDto = new CeQueueDto();
queueDto.setTaskType("fake");
queueDto.setUuid("TASK_1");
@ -152,27 +160,85 @@ public class TaskActionTest {
dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
dbTester.commit();
ws.newRequest()
.setMediaType(MediaTypes.JSON)
.setParam("id", "TASK_1")
.execute();
}
@Test
public void not_fail_on_queue_task_not_linked_on_project_with_global_scan_permissions() {
userSession.login("john").setGlobalPermissions(SCAN_EXECUTION);
CeQueueDto queueDto = new CeQueueDto();
queueDto.setTaskType("fake");
queueDto.setUuid("TASK_1");
queueDto.setStatus(CeQueueDto.Status.PENDING);
dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
dbTester.commit();
ws.newRequest()
.setMediaType(MediaTypes.JSON)
.setParam("id", "TASK_1")
.execute();
}
@Test
public void fail_on_queue_task_not_linked_on_project_if_not_admin_nor_scan_permission() {
userSession.login("john").setGlobalPermissions(PREVIEW_EXECUTION);
CeQueueDto queueDto = new CeQueueDto();
queueDto.setTaskType("fake");
queueDto.setUuid("TASK_1");
queueDto.setStatus(CeQueueDto.Status.PENDING);
dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
dbTester.commit();
expectedException.expect(ForbiddenException.class);
ws.newRequest()
.setMediaType(MediaTypes.PROTOBUF)
.setParam("id", "TASK_1")
.execute();
}
@Test
public void not_fail_on_queue_task_linked_on_project_with_project_scan_permission() {
userSession.login("john").addProjectUuidPermissions(SCAN_EXECUTION, PROJECT.uuid());
CeQueueDto queueDto = new CeQueueDto();
queueDto.setTaskType("fake");
queueDto.setUuid("TASK_1");
queueDto.setStatus(CeQueueDto.Status.PENDING);
queueDto.setComponentUuid(PROJECT.uuid());
dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
dbTester.commit();
ws.newRequest()
.setMediaType(MediaTypes.JSON)
.setParam("id", "TASK_1")
.execute();
}
@Test
public void not_fail_on_archived_task_linked_on_project_with_project_scan_permission() throws Exception {
userSession.login("john").addProjectUuidPermissions(SCAN_EXECUTION, PROJECT.uuid());
CeQueueDto queueDto = new CeQueueDto();
queueDto.setTaskType(CeTaskTypes.REPORT);
queueDto.setUuid("TASK_1");
queueDto.setComponentUuid(PROJECT.uuid());
CeActivityDto activityDto = new CeActivityDto(queueDto);
activityDto.setStatus(CeActivityDto.Status.FAILED);
activityDto.setExecutionTimeMs(500L);
activityDto.setSnapshotId(123_456L);
activityDto.setComponentUuid(PROJECT.uuid());
dbTester.getDbClient().ceActivityDao().insert(dbTester.getSession(), activityDto);
dbTester.commit();
ws.newRequest()
.setMediaType(MediaTypes.PROTOBUF)
.setParam("id", "TASK_1")
.execute();
}
@Test
public void support_json_response_with_scan_permissions() {
userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
CeQueueDto queueDto = new CeQueueDto();
queueDto.setTaskType("fake");
queueDto.setUuid("TASK_1");
queueDto.setStatus(CeQueueDto.Status.PENDING);
dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
dbTester.commit();
TestResponse wsResponse = ws.newRequest()
.setMediaType(MediaTypes.JSON)
.setParam("id", "TASK_1")
.execute();
assertJson(wsResponse.getInput()).isSimilarTo("{\"task\":{}}");
}
}