Merge "Allow admins to disable remote plugin installation"

This commit is contained in:
Shawn Pearce 2014-02-19 23:23:02 +00:00 committed by Gerrit Code Review
commit 3fa55d48c8
9 changed files with 70 additions and 8 deletions

View File

@ -2317,6 +2317,12 @@ may force reloading with link:cmd-plugin.html[gerrit plugin reload].
+
Default is 1 minute.
[[plugins.allowRemoteAdmin]]plugins.allowRemoteAdmin::
+
Enable remote installation, enable and disable of plugins over HTTP
and SSH. If set to true Administrators can install new plugins
remotely, or disable existing plugins. Defaults to false.
[[receive]]
=== Section receive

View File

@ -17,6 +17,7 @@ package com.google.gerrit.server.plugins;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.server.plugins.DisablePlugin.Input;
import com.google.gerrit.server.plugins.ListPlugins.PluginInfo;
@ -35,7 +36,12 @@ class DisablePlugin implements RestModifyView<PluginResource, Input> {
}
@Override
public PluginInfo apply(PluginResource resource, Input input) {
public PluginInfo apply(PluginResource resource, Input input)
throws MethodNotAllowedException {
if (!loader.isRemoteAdminEnabled()) {
throw new MethodNotAllowedException(
"remote plugin administration is disabled");
}
String name = resource.getName();
loader.disablePlugins(ImmutableSet.of(name));
return new PluginInfo(loader.get(name));

View File

@ -17,6 +17,7 @@ package com.google.gerrit.server.plugins;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.server.plugins.EnablePlugin.Input;
@ -40,7 +41,11 @@ class EnablePlugin implements RestModifyView<PluginResource, Input> {
@Override
public PluginInfo apply(PluginResource resource, Input input)
throws ResourceConflictException {
throws ResourceConflictException, MethodNotAllowedException {
if (!loader.isRemoteAdminEnabled()) {
throw new MethodNotAllowedException(
"remote plugin administration is disabled");
}
String name = resource.getName();
try {
loader.enablePlugins(ImmutableSet.of(name));

View File

@ -18,6 +18,7 @@ import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.DefaultInput;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.RawInput;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestModifyView;
@ -53,8 +54,11 @@ class InstallPlugin implements RestModifyView<TopLevelResource, Input> {
}
@Override
public Response<PluginInfo> apply(TopLevelResource resource,
Input input) throws BadRequestException, IOException {
public Response<PluginInfo> apply(TopLevelResource resource, Input input)
throws BadRequestException, MethodNotAllowedException, IOException {
if (!loader.isRemoteAdminEnabled()) {
throw new MethodNotAllowedException("remote installation is disabled");
}
try {
InputStream in;
if (input.raw != null) {
@ -102,8 +106,8 @@ class InstallPlugin implements RestModifyView<TopLevelResource, Input> {
}
@Override
public Response<PluginInfo> apply(PluginResource resource,
Input input) throws BadRequestException, IOException {
public Response<PluginInfo> apply(PluginResource resource, Input input)
throws BadRequestException, MethodNotAllowedException, IOException {
return new InstallPlugin(loader, resource.getName(), false)
.apply(TopLevelResource.INSTANCE, input);
}

View File

@ -90,6 +90,7 @@ public class PluginLoader implements LifecycleListener {
private final Provider<PluginCleanerTask> cleaner;
private final PluginScannerThread scanner;
private final Provider<String> urlProvider;
private final boolean remoteAdmin;
@Inject
public PluginLoader(SitePaths sitePaths,
@ -113,6 +114,9 @@ public class PluginLoader implements LifecycleListener {
cleaner = pct;
urlProvider = provider;
remoteAdmin =
cfg.getBoolean("plugins", null, "allowRemoteAdmin", false);
long checkFrequency = ConfigUtil.getTimeUnit(cfg,
"plugins", null, "checkFrequency",
TimeUnit.MINUTES.toMillis(1), TimeUnit.MILLISECONDS);
@ -123,6 +127,10 @@ public class PluginLoader implements LifecycleListener {
}
}
public boolean isRemoteAdminEnabled() {
return remoteAdmin;
}
public Plugin get(String name) {
Plugin p = running.get(name);
if (p != null) {
@ -143,6 +151,8 @@ public class PluginLoader implements LifecycleListener {
public void installPluginFromStream(String originalName, InputStream in)
throws IOException, PluginInstallException {
checkRemoteInstall();
String fileName = originalName;
if (!(fileName.endsWith(".jar") || fileName.endsWith(".js"))) {
fileName += ".jar";
@ -227,6 +237,12 @@ public class PluginLoader implements LifecycleListener {
}
public void disablePlugins(Set<String> names) {
if (!isRemoteAdminEnabled()) {
log.warn("Remote plugin administration is disabled,"
+ " ignoring disablePlugins(" + names + ")");
return;
}
synchronized (this) {
for (String name : names) {
Plugin active = running.get(name);
@ -255,6 +271,12 @@ public class PluginLoader implements LifecycleListener {
}
public void enablePlugins(Set<String> names) throws PluginInstallException {
if (!isRemoteAdminEnabled()) {
log.warn("Remote plugin administration is disabled,"
+ " ignoring enablePlugins(" + names + ")");
return;
}
synchronized (this) {
for (String name : names) {
Plugin off = disabled.get(name);
@ -748,4 +770,10 @@ public class PluginLoader implements LifecycleListener {
String fullExt = "." + ext;
return fileName.endsWith(fullExt) || fileName.endsWith(fullExt + ".disabled");
}
private void checkRemoteInstall() throws PluginInstallException {
if (!isRemoteAdminEnabled()) {
throw new PluginInstallException("remote installation is disabled");
}
}
}

View File

@ -17,6 +17,7 @@ package com.google.gerrit.server.plugins;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AcceptsCreate;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestCollection;
import com.google.gerrit.extensions.restapi.RestView;
@ -58,7 +59,10 @@ public class PluginsCollection implements
@SuppressWarnings("unchecked")
@Override
public InstallPlugin create(TopLevelResource parent, IdString id)
throws ResourceNotFoundException {
throws ResourceNotFoundException, MethodNotAllowedException {
if (!loader.isRemoteAdminEnabled()) {
throw new MethodNotAllowedException("remote installation is disabled");
}
return new InstallPlugin(loader, id.get(), true /* created */);
}

View File

@ -41,6 +41,9 @@ final class PluginEnableCommand extends SshCommand {
@Override
protected void run() throws UnloggedFailure {
if (!loader.isRemoteAdminEnabled()) {
throw die("remote plugin administration is disabled");
}
if (names != null && !names.isEmpty()) {
try {
loader.enablePlugins(Sets.newHashSet(names));

View File

@ -56,6 +56,9 @@ final class PluginInstallCommand extends SshCommand {
@Override
protected void run() throws UnloggedFailure {
if (!loader.isRemoteAdminEnabled()) {
throw die("remote installation is disabled");
}
if (Strings.isNullOrEmpty(source)) {
throw die("Argument \"-|URL\" is required");
}

View File

@ -39,7 +39,10 @@ final class PluginRemoveCommand extends SshCommand {
private PluginLoader loader;
@Override
protected void run() {
protected void run() throws UnloggedFailure {
if (!loader.isRemoteAdminEnabled()) {
throw die("remote plugin administration is disabled");
}
if (names != null && !names.isEmpty()) {
loader.disablePlugins(Sets.newHashSet(names));
}