GetUserFilter: Allow to include username in servlet response header

Add a new setting, http.addUserAsResponseHeader, which when enabled
causes the servlet response to include a 'User' header that contains
the name of the logged in user.

This will enable reverse proxies to log the name of the user that
issued the http request.

The new setting is disabled by default.

Change-Id: I5c3c783813f3aa71209320610bb8168a51305cba
This commit is contained in:
Gustaf Lundh 2018-05-02 10:52:11 +02:00 committed by David Pursehouse
parent 1d3d690765
commit e45c333b70
3 changed files with 46 additions and 10 deletions

View File

@ -2401,6 +2401,14 @@ Pattern to print user in Tomcat AccessLog.
+
Default value is true.
[[http.addUserAsResponseHeader]]http.addUserAsResponseHeader::
+
If true, the header 'User' will be added to the list of response headers so it
can be accessed from a reverse proxy for logging purposes.
+
Default value is false.
[[httpd]]
=== Section httpd

View File

@ -14,6 +14,7 @@
package com.google.gerrit.httpd;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.GerritServerConfig;
@ -28,33 +29,49 @@ import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.Config;
/** Stores user as a request attribute, so servlets can access it outside of the request scope. */
/**
* Stores user as a request attribute and/or response header, so servlets and reverse proxies can
* access it outside of the request/response scope.
*/
@Singleton
public class GetUserFilter implements Filter {
public static final String REQ_ATTR_KEY = "User";
public static final String USER_ATTR_KEY = "User";
public static class Module extends ServletModule {
private final boolean enabled;
private final boolean reqEnabled;
private final boolean resEnabled;
@Inject
Module(@GerritServerConfig Config cfg) {
enabled = cfg.getBoolean("http", "addUserAsRequestAttribute", true);
reqEnabled = cfg.getBoolean("http", "addUserAsRequestAttribute", true);
resEnabled = cfg.getBoolean("http", "addUserAsResponseHeader", false);
}
@Override
protected void configureServlets() {
if (enabled) {
filter("/*").through(GetUserFilter.class);
if (resEnabled || reqEnabled) {
ImmutableMap.Builder<String, String> initParams = ImmutableMap.builder();
if (reqEnabled) {
initParams.put("reqEnabled", "");
}
if (resEnabled) {
initParams.put("resEnabled", "");
}
filter("/*").through(GetUserFilter.class, initParams.build());
}
}
}
private final Provider<CurrentUser> userProvider;
private boolean reqEnabled;
private boolean resEnabled;
@Inject
GetUserFilter(Provider<CurrentUser> userProvider) {
this.userProvider = userProvider;
@ -65,11 +82,19 @@ public class GetUserFilter implements Filter {
throws IOException, ServletException {
CurrentUser user = userProvider.get();
if (user != null && user.isIdentifiedUser()) {
IdentifiedUser who = user.asIdentifiedUser();
String loggableName;
if (who.getUserName() != null && !who.getUserName().isEmpty()) {
req.setAttribute(REQ_ATTR_KEY, who.getUserName());
loggableName = who.getUserName();
} else {
req.setAttribute(REQ_ATTR_KEY, "a/" + who.getAccountId());
loggableName = "a/" + who.getAccountId();
}
if (reqEnabled) {
req.setAttribute(USER_ATTR_KEY, loggableName);
}
if (resEnabled && resp instanceof HttpServletResponse) {
((HttpServletResponse) resp).addHeader(USER_ATTR_KEY, loggableName);
}
}
chain.doFilter(req, resp);
@ -79,5 +104,8 @@ public class GetUserFilter implements Filter {
public void destroy() {}
@Override
public void init(FilterConfig arg0) {}
public void init(FilterConfig arg0) {
reqEnabled = arg0.getInitParameter("reqEnabled") != null ? true : false;
resEnabled = arg0.getInitParameter("resEnabled") != null ? true : false;
}
}

View File

@ -89,7 +89,7 @@ class HttpLog extends AbstractLifeCycle implements RequestLog {
String uri = req.getRequestURI();
uri = redactQueryString(uri, req.getQueryString());
String user = (String) req.getAttribute(GetUserFilter.REQ_ATTR_KEY);
String user = (String) req.getAttribute(GetUserFilter.USER_ATTR_KEY);
if (user != null) {
event.setProperty(P_USER, user);
}