Allow anonymous clones when pull-replication plugin is enabled.
When the command `git clone` is executed over http, behind the scenes it
does a request: `/info/refs?service=git-upload-pack`. Currently
`BearerAuthenticationFilter.java` filters ALL the `upload pack` requests
and therefore it checks the Bearer token header. This feature was added
to allow Bearer Token Authentication when `git fetch over http` is
executed from other Gerrit instances.
The fix allows to discriminate the `upload pack` requests, therefore
Bearer token header checking will be done just in the case of
`git fetch over http` from other Gerrit instances.
Bug: Issue 16548
Change-Id: I9873d92c88b8eb00c895a8e1cce18cae94199ac9
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/BearerAuthenticationFilter.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/BearerAuthenticationFilter.java
index 8147149..be71946 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/BearerAuthenticationFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/BearerAuthenticationFilter.java
@@ -44,6 +44,7 @@
public class BearerAuthenticationFilter extends AllRequestFilter {
private static final String BEARER_TOKEN = "BearerToken";
+ private static final String BEARER_TOKEN_PREFIX = "Bearer";
private final DynamicItem<WebSession> session;
private final String pluginName;
private final PullReplicationInternalUser pluginUser;
@@ -79,13 +80,14 @@
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
String requestURI = httpRequest.getRequestURI();
+ Optional<String> authorizationHeader =
+ Optional.ofNullable(httpRequest.getHeader("Authorization"));
if (isBasicAuthenticationRequest(requestURI)) {
filterChain.doFilter(servletRequest, servletResponse);
- } else if (isPullReplicationApiRequest(requestURI) || isGitUploadPackRequest(httpRequest)) {
- Optional<String> authorizationHeader =
- Optional.ofNullable(httpRequest.getHeader("Authorization"));
-
+ } else if (isPullReplicationApiRequest(requestURI)
+ || (isGitUploadPackRequest(httpRequest)
+ && isAuthenticationHeaderWithBearerToken(authorizationHeader))) {
if (isBearerTokenAuthenticated(authorizationHeader, bearerToken))
try (ManualRequestContext ctx =
new ManualRequestContext(pluginUser, threadLocalRequestContext.get())) {
@@ -137,4 +139,8 @@
}
return Optional.empty();
}
+
+ private boolean isAuthenticationHeaderWithBearerToken(Optional<String> authorizationHeader) {
+ return authorizationHeader.map(h -> h.startsWith(BEARER_TOKEN_PREFIX)).orElse(false);
+ }
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/BearerAuthenticationFilterTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/BearerAuthenticationFilterTest.java
index 824496a..ca69f06 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/BearerAuthenticationFilterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/BearerAuthenticationFilterTest.java
@@ -16,7 +16,6 @@
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import static org.mockito.Mockito.atMost;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -108,17 +107,53 @@
}
@Test
- public void shouldAuthenticateWhenGitUploadPacket() throws ServletException, IOException {
+ public void shouldAuthenticateWhenGitUploadPack() throws ServletException, IOException {
authenticateAndFilter("any-prefix/git-upload-pack", NO_QUERY_PARAMETERS);
}
@Test
- public void shouldAuthenticateWhenGitUploadPacketInQueryParameter()
+ public void shouldAuthenticateWhenGitUploadPackInQueryParameter()
throws ServletException, IOException {
authenticateAndFilter("any-prefix", GIT_UPLOAD_PACK_QUERY_PARAMETER);
}
@Test
+ public void shouldGoNextInChainWhenGitUploadPackWithoutAuthenticationHeader()
+ throws ServletException, IOException {
+ when(httpServletRequest.getRequestURI()).thenReturn("any-prefix/git-upload-pack");
+
+ final BearerAuthenticationFilter filter =
+ new BearerAuthenticationFilter(
+ session,
+ pluginName,
+ pluginUser,
+ threadLocalRequestContextProvider,
+ "some-bearer-token");
+ filter.doFilter(httpServletRequest, httpServletResponse, filterChain);
+
+ verify(httpServletRequest).getHeader("Authorization");
+ verify(filterChain).doFilter(httpServletRequest, httpServletResponse);
+ }
+
+ @Test
+ public void shouldGoNextInChainWhenGitUploadPackWithAuthenticationHeaderDifferentThanBearer()
+ throws ServletException, IOException {
+ when(httpServletRequest.getRequestURI()).thenReturn("any-prefix/git-upload-pack");
+ when(httpServletRequest.getHeader("Authorization")).thenReturn("some-authorization");
+ final BearerAuthenticationFilter filter =
+ new BearerAuthenticationFilter(
+ session,
+ pluginName,
+ pluginUser,
+ threadLocalRequestContextProvider,
+ "some-bearer-token");
+ filter.doFilter(httpServletRequest, httpServletResponse, filterChain);
+
+ verify(httpServletRequest).getHeader("Authorization");
+ verify(filterChain).doFilter(httpServletRequest, httpServletResponse);
+ }
+
+ @Test
public void shouldBe401WhenBearerTokenDoesNotMatch() throws ServletException, IOException {
when(httpServletRequest.getRequestURI()).thenReturn("any-prefix/pull-replication~fetch");
when(httpServletRequest.getHeader("Authorization"))
@@ -171,6 +206,7 @@
filter.doFilter(httpServletRequest, httpServletResponse, filterChain);
verify(httpServletRequest).getRequestURI();
+ verify(httpServletRequest).getHeader("Authorization");
verify(httpServletResponse).sendError(SC_UNAUTHORIZED);
}
@@ -187,7 +223,7 @@
"some-bearer-token");
filter.doFilter(httpServletRequest, httpServletResponse, filterChain);
- verify(httpServletRequest, times(2)).getRequestURI();
+ verify(httpServletRequest).getHeader("Authorization");
verify(filterChain).doFilter(httpServletRequest, httpServletResponse);
}
@@ -206,7 +242,7 @@
"some-bearer-token");
filter.doFilter(httpServletRequest, httpServletResponse, filterChain);
- verify(httpServletRequest).getRequestURI();
+ verify(httpServletRequest).getHeader("Authorization");
verify(filterChain).doFilter(httpServletRequest, httpServletResponse);
}
}