Allow configuring trusted keys during signed push checking

Admins can specify key fingerprints in gerrit.config with
receive.trustedKey, which get passed to the public key web of trust
checker from the previous commit.

Change-Id: Ic44b83fd5ed2a9399fce23e55d312bafebd85cc1
This commit is contained in:
Dave Borowitz 2015-08-31 15:36:59 -04:00
parent 8e28957137
commit 1bb4949096
2 changed files with 48 additions and 0 deletions

View File

@ -2982,6 +2982,14 @@ Default is zero.
+
Common unit suffixes of 'k', 'm', or 'g' are supported.
[[receive.maxTrustDepth]]receive.maxTrustDepth::
+
If signed push validation is link:#receive.enableSignedPush[enabled],
set to the maximum depth to search when checking if a key is
link:#receive.trustedKey[trusted].
+
Default is 0, meaning only explicitly trusted keys are allowed.
[[receive.threadPoolSize]]receive.threadPoolSize::
+
Maximum size of the thread pool in which the change data in received packs is
@ -3000,6 +3008,25 @@ be specified using standard time unit abbreviations ('ms', 'sec',
Default is 2 minutes. If no unit is specified, milliseconds
is assumed.
[[receive.trustedKey]]receive.trustedKey::
+
List of GPG key fingerprints that should be considered trust roots by
the server when signed push validation is
link:#receive.enableSignedPush[enabled]. A key is trusted by the server
if it is either in this list, or a path of trust signatures leads from
the key to a configured trust root. The maximum length of the path is
determined by link:#receive.maxTrustDepth[`receive.maxTrustDepth`].
+
Key fingerprints can be displayed with `gpg --list-keys
--with-fingerprint`.
+
Trust signatures can be added to a key using the `tsign` command to
link:https://www.gnupg.org/documentation/manuals/gnupg/OpenPGP-Key-Management.html[
`gpg --edit-key`], after which the signed key should be re-uploaded.
+
If no keys are specified, web-of-trust checks are disabled. This is the
default behavior.
[[repository]]
=== Section repository

View File

@ -17,13 +17,16 @@ package com.google.gerrit.gpg;
import static com.google.gerrit.gpg.PublicKeyStore.keyIdToString;
import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_GPGKEY;
import com.google.common.base.CharMatcher;
import com.google.common.base.MoreObjects;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Ordering;
import com.google.common.io.BaseEncoding;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.reviewdb.client.AccountExternalId;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@ -32,10 +35,12 @@ import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.transport.PushCertificateIdent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
@ -56,10 +61,26 @@ public class GerritPublicKeyChecker extends PublicKeyChecker {
private final String webUrl;
private final Provider<IdentifiedUser> userProvider;
private static List<Fingerprint> getTrustedFingerprints(Config cfg) {
String[] strs = cfg.getStringList("receive", null, "trustedKey");
if (strs == null || strs.length == 0) {
return null;
}
List<Fingerprint> fps = new ArrayList<>(strs.length);
for (String str : strs) {
str = CharMatcher.WHITESPACE.removeFrom(str).toUpperCase();
fps.add(new Fingerprint(BaseEncoding.base16().decode(str)));
}
return fps;
}
@Inject
GerritPublicKeyChecker(
@GerritServerConfig Config cfg,
@CanonicalWebUrl String webUrl,
Provider<IdentifiedUser> userProvider) {
super(cfg.getInt("receive", null, "maxTrustDepth", 0),
getTrustedFingerprints(cfg));
this.webUrl = webUrl;
this.userProvider = userProvider;
}