diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt index 865dd0580c..8d134ffb30 100644 --- a/Documentation/config-gerrit.txt +++ b/Documentation/config-gerrit.txt @@ -390,6 +390,18 @@ This parameter only affects git over http and git over SSH traffic. + By default this is set to false. +[[auth.enableRunAs]]auth.enableRunAs:: ++ +If true HTTP REST APIs will accept the `X-Gerrit-RunAs` HTTP request +header from any users granted the link:access-control.html#capability_runAs[Run As] +capability. The header and capability permit the authenticated user +to impersonate another account. ++ +If false the feature is disabled and cannot be re-enabled without +editing gerrit.config and restarting the server. ++ +Default is true. + [[cache]]Section cache ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RunAsFilter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RunAsFilter.java index 8685fdf799..37617e1737 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RunAsFilter.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RunAsFilter.java @@ -21,12 +21,14 @@ import com.google.gerrit.httpd.restapi.RestApiServlet; import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.account.AccountResolver; +import com.google.gerrit.server.config.GerritServerConfig; import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.servlet.ServletModule; +import org.eclipse.jgit.lib.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,26 +56,37 @@ class RunAsFilter implements Filter { } } + private final boolean enabled; private final Provider session; private final AccountResolver accountResolver; @Inject - RunAsFilter(Provider session, AccountResolver accountResolver) { + RunAsFilter(@GerritServerConfig Config config, + Provider session, + AccountResolver accountResolver) { + this.enabled = config.getBoolean("auth", null, "enableRunAs", true); this.session = session; this.accountResolver = accountResolver; } @Override - public void doFilter(ServletRequest request, ServletResponse res, + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; String runas = req.getHeader(RUN_AS); if (runas != null) { + if (!enabled) { + RestApiServlet.replyError(res, + SC_FORBIDDEN, + RUN_AS + " disabled by auth.enableRunAs = false"); + return; + } + CurrentUser self = session.get().getCurrentUser(); if (!self.getCapabilities().canRunAs()) { - RestApiServlet.replyError( - (HttpServletResponse) res, + RestApiServlet.replyError(res, SC_FORBIDDEN, "not permitted to use " + RUN_AS); return; @@ -84,15 +97,13 @@ class RunAsFilter implements Filter { target = accountResolver.find(runas); } catch (OrmException e) { log.warn("cannot resolve account for " + RUN_AS, e); - RestApiServlet.replyError( - (HttpServletResponse) res, + RestApiServlet.replyError(res, SC_INTERNAL_SERVER_ERROR, "cannot resolve " + RUN_AS); return; } if (target == null) { - RestApiServlet.replyError( - (HttpServletResponse) res, + RestApiServlet.replyError(res, SC_FORBIDDEN, "no account matches " + RUN_AS); return;