Merge "Add a 'banner' extension point" into stable-2.16
diff --git a/Documentation/cmd-review.txt b/Documentation/cmd-review.txt
index 6fe24815..27a39f4 100644
--- a/Documentation/cmd-review.txt
+++ b/Documentation/cmd-review.txt
@@ -15,9 +15,7 @@
[--abandon | --restore]
[--rebase]
[--move <BRANCH>]
- [--publish]
[--json | -j]
- [--delete]
[--verified <N>] [--code-review <N>]
[--label Label-Name=<N>]
[--tag TAG]
@@ -66,7 +64,7 @@
Read review input json from stdin. See
link:rest-api-changes.html#review-input[ReviewInput] entity for the
format.
- (option is mutually exclusive with --submit, --restore, --publish, --delete,
+ (option is mutually exclusive with --submit, --restore,
--abandon, --message, --rebase and --move)
--notify::
@@ -88,7 +86,7 @@
--abandon::
Abandon the specified change(s).
- (option is mutually exclusive with --submit, --restore, --publish, --delete,
+ (option is mutually exclusive with --submit, --restore,
--rebase, --move and --json)
--restore::
@@ -97,7 +95,7 @@
--rebase::
Rebase the specified change(s).
- (option is mutually exclusive with --abandon, --submit, --delete and --json)
+ (option is mutually exclusive with --abandon, --submit and --json)
--move::
Move the specified change(s).
@@ -106,7 +104,7 @@
--submit::
-s::
Submit the specified patch set(s) for merging.
- (option is mutually exclusive with --abandon, --publish --delete, --rebase
+ (option is mutually exclusive with --abandon, --rebase
and --json)
--code-review::
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index c65acb7..9a63503 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -2786,8 +2786,8 @@
}
----
-[[ssh-command-interception]]
-== SSH Command Interception
+[[ssh-command-creation-interception]]
+== SSH Command Creation Interception
Gerrit provides an extension point that allows a plugin to intercept
creation of SSH commands and override the functionality with its own
@@ -2910,6 +2910,40 @@
}
----
+[[ssh-command-execution-interception]]
+== SSH Command Execution Interception
+Gerrit provides an extension point that enables plugins to check and
+prevent an SSH command from being run.
+
+[source, java]
+----
+import com.google.gerrit.sshd.SshExecuteCommandInterceptor;
+
+@Singleton
+public class SshExecuteCommandInterceptorImpl implements SshExecuteCommandInterceptor {
+ private final Provider<SshSession> sessionProvider;
+
+ @Inject
+ SshExecuteCommandInterceptorImpl(Provider<SshSession> sessionProvider) {
+ this.sessionProvider = sessionProvider;
+ }
+
+ @Override
+ public boolean accept(String command, List<String> arguments) {
+ if (command.startsWith("gerrit") && !"10.1.2.3".equals(sessionProvider.get().getRemoteAddressAsString())) {
+ return false;
+ }
+ return true;
+ }
+}
+----
+
+And then declare it in your SSH module:
+[source, java]
+----
+ DynamicSet.bind(binder(), SshExecuteCommandInterceptor.class).to(SshExecuteCommandInterceptorImpl.class);
+----
+
Plugin authors should also consider binding their SubmitRule using a `Gerrit-BatchModule`.
See link:dev-plugins.html[Batch runtime] for more informations.
diff --git a/java/com/google/gerrit/pgm/init/SitePathInitializer.java b/java/com/google/gerrit/pgm/init/SitePathInitializer.java
index bc562cc..9d09461 100644
--- a/java/com/google/gerrit/pgm/init/SitePathInitializer.java
+++ b/java/com/google/gerrit/pgm/init/SitePathInitializer.java
@@ -107,6 +107,7 @@
extractMailExample("Abandoned.soy");
extractMailExample("AbandonedHtml.soy");
extractMailExample("AddKey.soy");
+ extractMailExample("AddKeyHtml.soy");
extractMailExample("ChangeFooter.soy");
extractMailExample("ChangeFooterHtml.soy");
extractMailExample("ChangeSubject.soy");
diff --git a/java/com/google/gerrit/sshd/DispatchCommand.java b/java/com/google/gerrit/sshd/DispatchCommand.java
index 4c9ca91..68962db 100644
--- a/java/com/google/gerrit/sshd/DispatchCommand.java
+++ b/java/com/google/gerrit/sshd/DispatchCommand.java
@@ -18,6 +18,7 @@
import com.google.common.base.Throwables;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Atomics;
+import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.server.args4j.SubcommandHandler;
import com.google.gerrit.server.permissions.GlobalPermission;
@@ -44,6 +45,7 @@
private final PermissionBackend permissionBackend;
private final Map<String, CommandProvider> commands;
private final AtomicReference<Command> atomicCmd;
+ private final DynamicSet<SshExecuteCommandInterceptor> commandInterceptors;
@Argument(index = 0, required = false, metaVar = "COMMAND", handler = SubcommandHandler.class)
private String commandName;
@@ -52,10 +54,14 @@
private List<String> args = new ArrayList<>();
@Inject
- DispatchCommand(PermissionBackend permissionBackend, @Assisted Map<String, CommandProvider> all) {
+ DispatchCommand(
+ PermissionBackend permissionBackend,
+ DynamicSet<SshExecuteCommandInterceptor> commandInterceptors,
+ @Assisted Map<String, CommandProvider> all) {
this.permissionBackend = permissionBackend;
commands = all;
atomicCmd = Atomics.newReference();
+ this.commandInterceptors = commandInterceptors;
}
Map<String, CommandProvider> getMap() {
@@ -84,19 +90,29 @@
final Command cmd = p.getProvider().get();
checkRequiresCapability(cmd);
+ String actualCommandName = commandName;
if (cmd instanceof BaseCommand) {
final BaseCommand bc = (BaseCommand) cmd;
- if (getName().isEmpty()) {
- bc.setName(commandName);
- } else {
- bc.setName(getName() + " " + commandName);
+ if (!getName().isEmpty()) {
+ actualCommandName = getName() + " " + commandName;
}
+ bc.setName(actualCommandName);
bc.setArguments(args.toArray(new String[args.size()]));
} else if (!args.isEmpty()) {
throw die(commandName + " does not take arguments");
}
+ for (SshExecuteCommandInterceptor commandInterceptor : commandInterceptors) {
+ if (!commandInterceptor.accept(actualCommandName, args)) {
+ throw new UnloggedFailure(
+ 126,
+ String.format(
+ "blocked by %s, contact gerrit administrators for more details",
+ commandInterceptor.name()));
+ }
+ }
+
provideStateTo(cmd);
atomicCmd.set(cmd);
cmd.start(env);
diff --git a/java/com/google/gerrit/sshd/SshExecuteCommandInterceptor.java b/java/com/google/gerrit/sshd/SshExecuteCommandInterceptor.java
new file mode 100644
index 0000000..ee60670
--- /dev/null
+++ b/java/com/google/gerrit/sshd/SshExecuteCommandInterceptor.java
@@ -0,0 +1,35 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.sshd;
+
+import com.google.gerrit.extensions.annotations.ExtensionPoint;
+import java.util.List;
+
+@ExtensionPoint
+public interface SshExecuteCommandInterceptor {
+
+ /**
+ * Check the command and return false if this command must not be run.
+ *
+ * @param command the command
+ * @param arguments the list of arguments
+ * @return whether or not this command with these arguments can be executed
+ */
+ boolean accept(String command, List<String> arguments);
+
+ default String name() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/java/com/google/gerrit/sshd/SshModule.java b/java/com/google/gerrit/sshd/SshModule.java
index acdc958..df1f633 100644
--- a/java/com/google/gerrit/sshd/SshModule.java
+++ b/java/com/google/gerrit/sshd/SshModule.java
@@ -106,6 +106,7 @@
DynamicMap.mapOf(binder(), DynamicOptions.DynamicBean.class);
DynamicItem.itemOf(binder(), SshCreateCommandInterceptor.class);
+ DynamicSet.setOf(binder(), SshExecuteCommandInterceptor.class);
listener().toInstance(registerInParentInjectors());
listener().to(SshLog.class);
diff --git a/lib/jgit/jgit.bzl b/lib/jgit/jgit.bzl
index 7120c21..8fe8b14 100644
--- a/lib/jgit/jgit.bzl
+++ b/lib/jgit/jgit.bzl
@@ -1,10 +1,10 @@
load("//tools/bzl:maven_jar.bzl", "MAVEN_CENTRAL", "maven_jar")
-_JGIT_VERS = "5.1.6.201903130242-r"
+_JGIT_VERS = "5.1.7.201904200442-r"
_DOC_VERS = _JGIT_VERS # Set to _JGIT_VERS unless using a snapshot
-JGIT_DOC_URL = "http://download.eclipse.org/jgit/site/" + _DOC_VERS + "/apidocs"
+JGIT_DOC_URL = "https://download.eclipse.org/jgit/site/" + _DOC_VERS + "/apidocs"
_JGIT_REPO = MAVEN_CENTRAL # Leave here even if set to MAVEN_CENTRAL.
@@ -40,28 +40,28 @@
name = "jgit-lib",
artifact = "org.eclipse.jgit:org.eclipse.jgit:" + _JGIT_VERS,
repository = _JGIT_REPO,
- sha1 = "c33db190745a8a40524d3076f033ba2ee4616a64",
- src_sha1 = "f0e33171d3d413c5a94f07794aef7b71a35772f6",
+ sha1 = "ef1f744a1117e3d8916f3770486502a56d241b16",
+ src_sha1 = "7bf5b5298f8936e959a92f62b5151d58feb9c00a",
unsign = True,
)
maven_jar(
name = "jgit-servlet",
artifact = "org.eclipse.jgit:org.eclipse.jgit.http.server:" + _JGIT_VERS,
repository = _JGIT_REPO,
- sha1 = "86564c102e81a76f67630d4fde862d137e24c63a",
+ sha1 = "8306e221fb50985247138adb8ffb0f4cd74c5e9a",
unsign = True,
)
maven_jar(
name = "jgit-archive",
artifact = "org.eclipse.jgit:org.eclipse.jgit.archive:" + _JGIT_VERS,
repository = _JGIT_REPO,
- sha1 = "f4ebfa91f4c988f37648b3087830a83973a975be",
+ sha1 = "fefb13ab8331cc8b13a15b653b1e057de7d3e514",
)
maven_jar(
name = "jgit-junit",
artifact = "org.eclipse.jgit:org.eclipse.jgit.junit:" + _JGIT_VERS,
repository = _JGIT_REPO,
- sha1 = "b2e512e920afbac405a678efe92e3b4bacb9a1df",
+ sha1 = "f73f1eacc38f8329d9453f1d0353e82404379a89",
unsign = True,
)
diff --git a/tools/bzl/javadoc.bzl b/tools/bzl/javadoc.bzl
index fcf9f33..6387210 100644
--- a/tools/bzl/javadoc.bzl
+++ b/tools/bzl/javadoc.bzl
@@ -23,7 +23,7 @@
transitive_jar_paths = [j.path for j in transitive_jars.to_list()]
dir = ctx.outputs.zip.path + ".dir"
source = ctx.outputs.zip.path + ".source"
- external_docs = ["http://docs.oracle.com/javase/8/docs/api"] + ctx.attr.external_docs
+ external_docs = ["https://docs.oracle.com/javase/8/docs/api"] + ctx.attr.external_docs
cmd = [
"TZ=UTC",
"export TZ",
diff --git a/tools/js/npm_pack.py b/tools/js/npm_pack.py
index f14262a..57f3166 100755
--- a/tools/js/npm_pack.py
+++ b/tools/js/npm_pack.py
@@ -54,7 +54,7 @@
name, version = args
filename = '%s-%s.tgz' % (name, version)
- url = 'http://registry.npmjs.org/%s/-/%s' % (name, filename)
+ url = 'https://registry.npmjs.org/%s/-/%s' % (name, filename)
tmpdir = tempfile.mkdtemp()
tgz = os.path.join(tmpdir, filename)
diff --git a/tools/util.py b/tools/util.py
index 172ecfe..947e2c0 100644
--- a/tools/util.py
+++ b/tools/util.py
@@ -16,9 +16,9 @@
REPO_ROOTS = {
'ECLIPSE': 'https://repo.eclipse.org/content/groups/releases',
- 'GERRIT': 'http://gerrit-maven.storage.googleapis.com',
+ 'GERRIT': 'https://gerrit-maven.storage.googleapis.com',
'GERRIT_API': 'https://gerrit-api.commondatastorage.googleapis.com/release',
- 'MAVEN_CENTRAL': 'http://repo1.maven.org/maven2',
+ 'MAVEN_CENTRAL': 'https://repo1.maven.org/maven2',
'MAVEN_LOCAL': 'file://' + path.expanduser('~/.m2/repository'),
'MAVEN_SNAPSHOT': 'https://oss.sonatype.org/content/repositories/snapshots',
}
diff --git a/tools/util_test.py b/tools/util_test.py
index fa67696..1a389f5 100644
--- a/tools/util_test.py
+++ b/tools/util_test.py
@@ -29,18 +29,18 @@
def testKnownRedirect(self):
url = resolve_url('MAVEN_CENTRAL:foo.jar',
- {'MAVEN_CENTRAL': 'http://my.company.mirror/maven2'})
- self.assertEqual(url, 'http://my.company.mirror/maven2/foo.jar')
+ {'MAVEN_CENTRAL': 'https://my.company.mirror/maven2'})
+ self.assertEqual(url, 'https://my.company.mirror/maven2/foo.jar')
def testCustom(self):
- url = resolve_url('http://maven.example.com/release/foo.jar', {})
- self.assertEqual(url, 'http://maven.example.com/release/foo.jar')
+ url = resolve_url('https://maven.example.com/release/foo.jar', {})
+ self.assertEqual(url, 'https://maven.example.com/release/foo.jar')
def testCustomRedirect(self):
url = resolve_url('MAVEN_EXAMPLE:foo.jar',
{'MAVEN_EXAMPLE':
- 'http://maven.example.com/release'})
- self.assertEqual(url, 'http://maven.example.com/release/foo.jar')
+ 'https://maven.example.com/release'})
+ self.assertEqual(url, 'https://maven.example.com/release/foo.jar')
if __name__ == '__main__':