Restrict endpoints to change health status to admins
Change-Id: I01aca30a9b08ab14c770fb2e7e1afd3ef8507efc
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServlet.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServlet.java
index a121a89..bfdcc12 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServlet.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServlet.java
@@ -14,10 +14,14 @@
package com.ericsson.gerrit.plugins.highavailability.health;
+import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
+import com.google.gerrit.server.CurrentUser;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
@@ -31,20 +35,31 @@
private static final Logger log = LoggerFactory.getLogger(HealthServlet.class);
private static final long serialVersionUID = -1L;
+ private final Provider<CurrentUser> currentUserProvider;
private boolean healthy;
- HealthServlet() {
+ @Inject
+ HealthServlet(Provider<CurrentUser> currentUserProvider) {
+ this.currentUserProvider = currentUserProvider;
this.healthy = true;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse rsp) {
+ if (!currentUserProvider.get().getCapabilities().canAdministrateServer()) {
+ sendError(rsp, SC_FORBIDDEN);
+ return;
+ }
this.healthy = true;
rsp.setStatus(SC_NO_CONTENT);
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse rsp) {
+ if (!currentUserProvider.get().getCapabilities().canAdministrateServer()) {
+ sendError(rsp, SC_FORBIDDEN);
+ return;
+ }
this.healthy = false;
rsp.setStatus(SC_NO_CONTENT);
}
@@ -54,12 +69,16 @@
if (healthy) {
rsp.setStatus(SC_NO_CONTENT);
} else {
- try {
- rsp.sendError(SC_SERVICE_UNAVAILABLE);
- } catch (IOException e) {
- rsp.setStatus(SC_INTERNAL_SERVER_ERROR);
- log.error("Failed to send error response", e);
- }
+ sendError(rsp, SC_SERVICE_UNAVAILABLE);
+ }
+ }
+
+ private void sendError(HttpServletResponse rsp, int statusCode) {
+ try {
+ rsp.sendError(statusCode);
+ } catch (IOException e) {
+ rsp.setStatus(SC_INTERNAL_SERVER_ERROR);
+ log.error("Failed to send error response", e);
}
}
}
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServletTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServletTest.java
index 343df09..9d1bf2b 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServletTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServletTest.java
@@ -14,25 +14,41 @@
package com.ericsson.gerrit.plugins.highavailability.health;
+import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.account.CapabilityControl;
+import com.google.inject.Provider;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+@RunWith(MockitoJUnitRunner.class)
public class HealthServletTest {
+ @Mock private Provider<CurrentUser> currentUserProviderMock;
+ @Mock private CurrentUser currentUserMock;
+ @Mock private CapabilityControl capabilityControlMock;
+
private HealthServlet servlet;
@Before
public void setUp() throws Exception {
- servlet = new HealthServlet();
+ when(currentUserProviderMock.get()).thenReturn(currentUserMock);
+ when(currentUserMock.getCapabilities()).thenReturn(capabilityControlMock);
+ when(capabilityControlMock.canAdministrateServer()).thenReturn(true);
+ servlet = new HealthServlet(currentUserProviderMock);
}
@Test
@@ -58,6 +74,17 @@
}
@Test
+ public void testTransitionToUnhealthyByNonAdmins() throws IOException {
+ assertIsHealthy();
+
+ when(capabilityControlMock.canAdministrateServer()).thenReturn(false);
+ HttpServletResponse responseMock = mock(HttpServletResponse.class);
+ servlet.doDelete(null, responseMock);
+ verify(responseMock).sendError(SC_FORBIDDEN);
+ assertIsHealthy();
+ }
+
+ @Test
public void testTransitionToHealty() throws IOException {
// first, mark as unhealthy
servlet.doDelete(null, mock(HttpServletResponse.class));
@@ -77,6 +104,19 @@
}
@Test
+ public void testTransitionToHealthyByNonAdmins() throws IOException {
+ // first, mark as unhealthy
+ servlet.doDelete(null, mock(HttpServletResponse.class));
+ assertIsUnhealthy();
+
+ when(capabilityControlMock.canAdministrateServer()).thenReturn(false);
+ HttpServletResponse responseMock = mock(HttpServletResponse.class);
+ servlet.doPost(null, responseMock);
+ verify(responseMock).sendError(SC_FORBIDDEN);
+ assertIsUnhealthy();
+ }
+
+ @Test
public void testErrorWhileSendingUnhealthyResponse() throws IOException {
HttpServletResponse responseMock = mock(HttpServletResponse.class);
servlet.doDelete(null, responseMock);