Add User to the http request attributes

GetUserFilter is adding the user to the request attribute so the user
who requested the URL is printed in the httpd_log but it is only
applied when running Gerrit with the embedded servlet container.

Move GetUserFilter from the gerrit-pgm to gerrit-httpd so it can be
applied when running Gerrit in a servlet container (e.g. Tomcat). Add
a parameter http.addUserAsRequestAttribute in gerrit config to
enable/disable this filter. It is enabled by default.

In tomcat, pattern %{User}r can be used in the AccessLog to print user
to get same functionality as httpd_log when running with the embedded
servlet container.

Change-Id: I591d594848a5b2d4aa9389965365e0621b39a51c
This commit is contained in:
Hugo Arès 2014-03-03 13:52:45 -05:00
parent a2467073ac
commit 88e33ac9f1
5 changed files with 42 additions and 26 deletions

View File

@ -1750,6 +1750,24 @@ Optional password to authenticate to the HTTP proxy with.
This property is honored only if the password does not This property is honored only if the password does not
appear in the http.proxy property above. appear in the http.proxy property above.
[[http.addUserAsRequestAttribute]]http.addUserAsRequestAttribute::
+
If true, 'User' attribute will be added to the request attributes so it
can be accessed outside the request scope (will be set to username or id
if username not configured).
+
This attribute can be used by the servlet container to log user in the
http access log.
+
When running the embedded servlet container, this attribute is used to
print user in the httpd_log.
+
* `%{User}r`
+
Pattern to print user in Tomcat AccessLog.
+
Default value is true.
[[httpd]] [[httpd]]
=== Section httpd === Section httpd

View File

@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package com.google.gerrit.pgm.http.jetty; package com.google.gerrit.httpd;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
@ -24,7 +25,6 @@ import com.google.inject.servlet.ServletModule;
import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Config;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import javax.servlet.Filter; import javax.servlet.Filter;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
@ -34,28 +34,27 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
/** /**
* Stores as a request attribute, so the {@link HttpLog} can include the the * Stores user as a request attribute, so the servlet container access log like
* user for the request outside of the request scope. * {@link HttpLog} can include the the user for the request outside of the
* request scope.
*/ */
@Singleton @Singleton
public class GetUserFilter implements Filter { public class GetUserFilter implements Filter {
static final String REQ_ATTR_KEY = CurrentUser.class.toString(); public static final String REQ_ATTR_KEY = "User";
public static class Module extends ServletModule { public static class Module extends ServletModule {
private boolean loggingEnabled; private final boolean enabled;
@Inject @Inject
Module(@GerritServerConfig final Config cfg) { Module(@GerritServerConfig final Config cfg) {
URI[] urls = JettyServer.listenURLs(cfg); enabled = cfg.getBoolean("http", "addUserAsRequestAttribute", true);
boolean reverseProxy = JettyServer.isReverseProxied(urls);
this.loggingEnabled = cfg.getBoolean("httpd", "requestLog", !reverseProxy);
} }
@Override @Override
protected void configureServlets() { protected void configureServlets() {
if (loggingEnabled) { if (enabled) {
filter("/*").through(GetUserFilter.class); filter("/*").through(GetUserFilter.class);
} }
} }
@ -72,7 +71,15 @@ public class GetUserFilter implements Filter {
public void doFilter( public void doFilter(
ServletRequest req, ServletResponse resp, FilterChain chain) ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException { throws IOException, ServletException {
req.setAttribute(REQ_ATTR_KEY, userProvider.get()); CurrentUser user = userProvider.get();
if (user != null && user.isIdentifiedUser()) {
IdentifiedUser who = (IdentifiedUser) user;
if (who.getUserName() != null && !who.getUserName().isEmpty()) {
req.setAttribute(REQ_ATTR_KEY, who.getUserName());
} else {
req.setAttribute(REQ_ATTR_KEY, "a/" + who.getAccountId());
}
}
chain.doFilter(req, resp); chain.doFilter(req, resp);
} }

View File

@ -21,6 +21,7 @@ import com.google.common.base.MoreObjects;
import com.google.gerrit.common.ChangeHookRunner; import com.google.gerrit.common.ChangeHookRunner;
import com.google.gerrit.httpd.AllRequestFilter; import com.google.gerrit.httpd.AllRequestFilter;
import com.google.gerrit.httpd.GerritOptions; import com.google.gerrit.httpd.GerritOptions;
import com.google.gerrit.httpd.GetUserFilter;
import com.google.gerrit.httpd.GitOverHttpModule; import com.google.gerrit.httpd.GitOverHttpModule;
import com.google.gerrit.httpd.H2CacheBasedWebSession; import com.google.gerrit.httpd.H2CacheBasedWebSession;
import com.google.gerrit.httpd.HttpCanonicalWebUrlProvider; import com.google.gerrit.httpd.HttpCanonicalWebUrlProvider;
@ -31,7 +32,6 @@ import com.google.gerrit.httpd.auth.openid.OpenIdModule;
import com.google.gerrit.httpd.plugins.HttpPluginModule; import com.google.gerrit.httpd.plugins.HttpPluginModule;
import com.google.gerrit.lifecycle.LifecycleManager; import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.lucene.LuceneIndexModule; import com.google.gerrit.lucene.LuceneIndexModule;
import com.google.gerrit.pgm.http.jetty.GetUserFilter;
import com.google.gerrit.pgm.http.jetty.JettyEnv; import com.google.gerrit.pgm.http.jetty.JettyEnv;
import com.google.gerrit.pgm.http.jetty.JettyModule; import com.google.gerrit.pgm.http.jetty.JettyModule;
import com.google.gerrit.pgm.http.jetty.ProjectQoSFilter; import com.google.gerrit.pgm.http.jetty.ProjectQoSFilter;

View File

@ -14,8 +14,7 @@
package com.google.gerrit.pgm.http.jetty; package com.google.gerrit.pgm.http.jetty;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.httpd.GetUserFilter;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.util.SystemLog; import com.google.gerrit.server.util.SystemLog;
import com.google.gerrit.server.util.TimeUtil; import com.google.gerrit.server.util.TimeUtil;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -66,11 +65,6 @@ class HttpLog extends AbstractLifeCycle implements RequestLog {
@Override @Override
public void log(final Request req, final Response rsp) { public void log(final Request req, final Response rsp) {
CurrentUser user = (CurrentUser) req.getAttribute(GetUserFilter.REQ_ATTR_KEY);
doLog(req, rsp, user);
}
private void doLog(Request req, Response rsp, CurrentUser user) {
final LoggingEvent event = new LoggingEvent( // final LoggingEvent event = new LoggingEvent( //
Logger.class.getName(), // fqnOfCategoryClass Logger.class.getName(), // fqnOfCategoryClass
log, // logger log, // logger
@ -90,13 +84,9 @@ class HttpLog extends AbstractLifeCycle implements RequestLog {
uri = uri + "?" + qs; uri = uri + "?" + qs;
} }
if (user != null && user.isIdentifiedUser()) { String user = (String) req.getAttribute(GetUserFilter.REQ_ATTR_KEY);
IdentifiedUser who = (IdentifiedUser) user; if (user != null) {
if (who.getUserName() != null && !who.getUserName().isEmpty()) { event.setProperty(P_USER, user);
event.setProperty(P_USER, who.getUserName());
} else {
event.setProperty(P_USER, "a/" + who.getAccountId());
}
} }
set(event, P_HOST, req.getRemoteAddr()); set(event, P_HOST, req.getRemoteAddr());

View File

@ -344,6 +344,7 @@ public class WebAppInitializer extends GuiceServletContextListener
if (authConfig.getAuthType() == AuthType.OPENID) { if (authConfig.getAuthType() == AuthType.OPENID) {
modules.add(new OpenIdModule()); modules.add(new OpenIdModule());
} }
modules.add(sysInjector.getInstance(GetUserFilter.Module.class));
return sysInjector.createChildInjector(modules); return sysInjector.createChildInjector(modules);
} }