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