Convert runAs to PermissionBackend
Change-Id: Ia08189d864388b45c7f11b41cc835fda57d7e03d
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 4862a70..47850c4 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
@@ -19,11 +19,15 @@
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.config.AuthConfig;
+import com.google.gerrit.server.permissions.GlobalPermission;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -57,6 +61,7 @@
private final Provider<ReviewDb> db;
private final boolean enabled;
private final DynamicItem<WebSession> session;
+ private final PermissionBackend permissionBackend;
private final AccountResolver accountResolver;
@Inject
@@ -64,10 +69,12 @@
Provider<ReviewDb> db,
AuthConfig config,
DynamicItem<WebSession> session,
+ PermissionBackend permissionBackend,
AccountResolver accountResolver) {
this.db = db;
this.enabled = config.isRunAsEnabled();
this.session = session;
+ this.permissionBackend = permissionBackend;
this.accountResolver = accountResolver;
}
@@ -85,12 +92,20 @@
}
CurrentUser self = session.get().getUser();
- if (!self.getCapabilities().canRunAs()
+ try {
+ if (!self.isIdentifiedUser()) {
// Always disallow for anonymous users, even if permitted by the ACL,
// because that would be crazy.
- || !self.isIdentifiedUser()) {
+ throw new AuthException("denied");
+ }
+ permissionBackend.user(self).check(GlobalPermission.RUN_AS);
+ } catch (AuthException e) {
replyError(req, res, SC_FORBIDDEN, "not permitted to use " + RUN_AS, null);
return;
+ } catch (PermissionBackendException e) {
+ log.warn("cannot check runAs", e);
+ replyError(req, res, SC_INTERNAL_SERVER_ERROR, RUN_AS + " unavailable", null);
+ return;
}
Account target;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java
index 5aab085..b4d9195 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java
@@ -112,11 +112,6 @@
return canPerform(GlobalCapability.ACCESS_DATABASE);
}
- /** @return true if the user can impersonate another user. */
- public boolean canRunAs() {
- return canPerform(GlobalCapability.RUN_AS);
- }
-
/** @return which priority queue the user's tasks should be submitted to. */
public QueueProvider.QueueType getQueueType() {
// If a non-generic group (that is not Anonymous Users or Registered Users)
@@ -245,8 +240,6 @@
return canMaintainServer();
case MODIFY_ACCOUNT:
return canModifyAccount();
- case RUN_AS:
- return canRunAs();
case VIEW_ALL_ACCOUNTS:
return canViewAllAccounts();
case VIEW_QUEUE:
@@ -265,6 +258,9 @@
case VIEW_CONNECTIONS:
case VIEW_PLUGINS:
return canPerform(perm.permissionName()) || canAdministrateServer();
+
+ case RUN_AS:
+ return canPerform(perm.permissionName());
}
throw new PermissionBackendException(perm + " unsupported");
}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
index 53a98eb..54371c1 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
@@ -18,11 +18,15 @@
import com.google.common.base.Throwables;
import com.google.common.util.concurrent.Atomics;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PeerDaemonUser;
import com.google.gerrit.server.config.AuthConfig;
+import com.google.gerrit.server.permissions.GlobalPermission;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.sshd.SshScope.Context;
import com.google.inject.Inject;
import java.io.IOException;
@@ -45,6 +49,7 @@
public final class SuExec extends BaseCommand {
private final SshScope sshScope;
private final DispatchCommandProvider dispatcher;
+ private final PermissionBackend permissionBackend;
private boolean enableRunAs;
private CurrentUser caller;
@@ -67,6 +72,7 @@
SuExec(
final SshScope sshScope,
@CommandName(Commands.ROOT) final DispatchCommandProvider dispatcher,
+ PermissionBackend permissionBackend,
final CurrentUser caller,
final SshSession session,
final IdentifiedUser.GenericFactory userFactory,
@@ -74,6 +80,7 @@
AuthConfig config) {
this.sshScope = sshScope;
this.dispatcher = dispatcher;
+ this.permissionBackend = permissionBackend;
this.caller = caller;
this.session = session;
this.userFactory = userFactory;
@@ -115,8 +122,14 @@
// OK.
} else if (!enableRunAs) {
throw die("suexec disabled by auth.enableRunAs = false");
- } else if (!caller.getCapabilities().canRunAs()) {
- throw die("suexec not permitted");
+ } else {
+ try {
+ permissionBackend.user(caller).check(GlobalPermission.RUN_AS);
+ } catch (AuthException e) {
+ throw die("suexec not permitted");
+ } catch (PermissionBackendException e) {
+ throw die("suexec not available: " + e);
+ }
}
}