relax git lfs write request check and improved tests for GitPermissionFilter

This commit is contained in:
Sebastian Sdorra
2017-06-01 10:11:42 +02:00
parent 880b0499e8
commit 2af11b1f9c
2 changed files with 117 additions and 36 deletions

View File

@@ -73,6 +73,8 @@ public class GitPermissionFilter extends ProviderPermissionFilter
/** Field description */
public static final String URI_REF_INFO = "/info/refs";
public static final String METHOD_LFS_UPLOAD = "PUT";
//~--- constructors ---------------------------------------------------------
@@ -129,21 +131,23 @@ public class GitPermissionFilter extends ProviderPermissionFilter
*/
@Override
protected boolean isWriteRequest(HttpServletRequest request) {
String uri = request.getRequestURI();
return uri.endsWith(URI_RECEIVE_PACK) ||
(uri.endsWith(URI_REF_INFO) && PARAMETER_VALUE_RECEIVE.equals(request.getParameter(PARAMETER_SERVICE))) ||
isLfsFileUpload(request);
return isReceivePackRequest(request) ||
isReceiveServiceRequest(request) ||
isLfsFileUpload(request);
}
private boolean isReceivePackRequest(HttpServletRequest request) {
return request.getRequestURI().endsWith(URI_RECEIVE_PACK);
}
private boolean isReceiveServiceRequest(HttpServletRequest request) {
return request.getRequestURI().endsWith(URI_REF_INFO)
&& PARAMETER_VALUE_RECEIVE.equals(request.getParameter(PARAMETER_SERVICE));
}
@VisibleForTesting
static boolean isLfsFileUpload(HttpServletRequest request) {
String regex = String.format("^%s%s/.+(\\.git)?/info/lfs/objects/[a-z0-9]{64}$", request.getContextPath(), GitServletModule.GIT_PATH);
return request.getRequestURI().matches(regex) && "PUT".equals(request.getMethod());
private static boolean isLfsFileUpload(HttpServletRequest request) {
return METHOD_LFS_UPLOAD.equalsIgnoreCase(request.getMethod());
}
}

View File

@@ -1,48 +1,125 @@
package sonia.scm.web;
import com.google.common.base.Charsets;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.servlet.ServletOutputStream;
import org.junit.Test;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import static org.mockito.Mockito.*;
import org.mockito.runners.MockitoJUnitRunner;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.repository.RepositoryProvider;
/**
* Unit tests for {@link GitPermissionFilter}.
*
* Created by omilke on 19.05.2017.
*/
@RunWith(MockitoJUnitRunner.class)
public class GitPermissionFilterTest {
@Mock
private RepositoryProvider repositoryProvider;
private final GitPermissionFilter permissionFilter = new GitPermissionFilter(
new ScmConfiguration(), repositoryProvider
);
@Mock
private HttpServletResponse response;
@Test
public void isLfsFileUpload() throws Exception {
HttpServletRequest mockedRequest = getRequestWithMethodAndPathInfo("PUT",
"/scm/git/git-lfs-demo.git/info/lfs/objects/8fcebeb5698230685f92028e560f8f1683ebc15ec82a620ffad5c12a3c19bdec");
assertThat((GitPermissionFilter.isLfsFileUpload(mockedRequest)), is(true));
mockedRequest = getRequestWithMethodAndPathInfo("GET",
"/scm/git/git-lfs-demo.git/info/lfs/objects/8fcebeb5698230685f92028e560f8f1683ebc15ec82a620ffad5c12a3c19bdec");
assertThat((GitPermissionFilter.isLfsFileUpload(mockedRequest)), is(false));
mockedRequest = getRequestWithMethodAndPathInfo("POST",
"/scm/git/git-lfs-demo.git/info/lfs/objects/8fcebeb5698230685f92028e560f8f1683ebc15ec82a620ffad5c12a3c19bdec");
assertThat((GitPermissionFilter.isLfsFileUpload(mockedRequest)), is(false));
mockedRequest = getRequestWithMethodAndPathInfo("POST",
"/scm/git/git-lfs-demo.git/info/lfs/objects/batch");
assertThat((GitPermissionFilter.isLfsFileUpload(mockedRequest)), is(false));
public void testIsWriteRequest() {
HttpServletRequest request = mockRequestWithMethodAndRequestURI("POST", "/scm/git/fanzy-project/git-receive-pack");
assertThat(permissionFilter.isWriteRequest(request), is(true));
request = mockRequestWithMethodAndRequestURI("GET", "/scm/git/fanzy-project/info/refs?service=git-receive-pack");
assertThat(permissionFilter.isWriteRequest(request), is(true));
request = mockRequestWithMethodAndRequestURI("GET", "/scm/git/fanzy-project/info/refs?service=some-other-service");
assertThat(permissionFilter.isWriteRequest(request), is(false));
request = mockRequestWithMethodAndRequestURI(
"PUT",
"/scm/git/git-lfs-demo.git/info/lfs/objects/8fcebeb5698230685f92028e560f8f1683ebc15ec82a620ffad5c12a3c19bdec"
);
assertThat(permissionFilter.isWriteRequest(request), is(true));
request = mockRequestWithMethodAndRequestURI(
"GET",
"/scm/git/git-lfs-demo.git/info/lfs/objects/8fcebeb5698230685f92028e560f8f1683ebc15ec82a620ffad5c12a3c19bdec"
);
assertThat(permissionFilter.isWriteRequest(request), is(false));
request = mockRequestWithMethodAndRequestURI("POST", "/scm/git/git-lfs-demo.git/info/lfs/objects/batch");
assertThat(permissionFilter.isWriteRequest(request), is(false));
}
private HttpServletRequest getRequestWithMethodAndPathInfo(String method, String pathInfo) {
private HttpServletRequest mockRequestWithMethodAndRequestURI(String method, String requestURI) {
HttpServletRequest mock = mock(HttpServletRequest.class);
when(mock.getMethod()).thenReturn(method);
when(mock.getRequestURI()).thenReturn(pathInfo);
when(mock.getRequestURI()).thenReturn(requestURI);
when(mock.getContextPath()).thenReturn("/scm");
return mock;
}
@Test
public void testSendNotEnoughPrivilegesErrorAsBrowser() throws IOException {
HttpServletRequest request = mockGitReceivePackServiceRequest();
permissionFilter.sendNotEnoughPrivilegesError(request, response);
verify(response).sendError(HttpServletResponse.SC_FORBIDDEN);
}
@Test
public void testSendNotEnoughPrivilegesErrorAsGitClient() throws IOException {
HttpServletRequest request = mockGitReceivePackServiceRequest();
when(request.getHeader("User-Agent")).thenReturn("git/2.9.3");
CapturingServletOutputStream stream = new CapturingServletOutputStream();
when(response.getOutputStream()).thenReturn(stream);
permissionFilter.sendNotEnoughPrivilegesError(request, response);
verify(response).setStatus(HttpServletResponse.SC_OK);
assertThat(stream.toString(), containsString("privileges"));
}
private HttpServletRequest mockGitReceivePackServiceRequest() {
HttpServletRequest request = mockRequestWithMethodAndRequestURI("GET", "/git/info/refs");
when(request.getParameter("service")).thenReturn("git-receive-pack");
return request;
}
private static class CapturingServletOutputStream extends ServletOutputStream {
private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
@Override
public void write(int b) throws IOException {
baos.write(b);
}
@Override
public void close() throws IOException {
baos.close();
}
@Override
public String toString() {
return baos.toString();
}
}
}