To help ensure contributor privacy, but still support gathering of contributor agreements as necessary, Gerrit encrypts all offline contact information gathered from users. This data is shipped to another server, typically at a different location, to make it more difficult for an attacker to obtain.
This feature is optional. If the crypto APIs aren’t installed
contactstore.url setting in
gerrit.config is not set,
Gerrit will not collect contact information from users.
Ensure Bouncy Castle Crypto API is available in the web application’s
CLASSPATH (e.g. in
'JETTY_HOME'/lib/plus for Jetty). Gerrit needs
bcpg-jdk\*-*.jar to be provided
for the contact encryption to work.
Ensure a proper JCE policy file is installed. By default most JRE installations forbid the use of a strong key, resulting in SecurityException messages when trying to encrypt the contact data. You need to obtain a strong JCE policy file and install it by hand. Look for the Unlimited Strength Jurisdiction Policy download.
Create a public/private key pair for contact data handling. Generate the keys on a protected system, where the resulting private key is unlikely to fall into the wrong hands.
Select to use a
DSA and Elgamal key type, as the public key will
be used for data encryption.
The information chosen for name, email and comment fields can be anything reasonable which would identify the contact store of this Gerrit instance. It is probably a good idea to not use a real person’s name here, but instead some sort of organizational role. The actual values chosen don’t matter later, and are only to help document the purpose of the key.
Choose a fairly long expiration period, such as 20 years. For most Gerrit instances, contact data will be written once, and rarely, if ever, read back.
Export the public key for Gerrit to use during encryption. The
public key must be stored in a file called
and reside inside of the
site_config directory. Armoring it
during export makes it easier to transport between systems, as
you can easily copy-and-paste the text. Gerrit can read both the
armored and unarmored formats.
gpg --export --armor KEYEMAIL >$site_path/etc/contact_information.pub
Consider storing the private key with some sort of key escrow service within your organization. Without the private key it is impossible to recover contact records.
Install a contact store implementation somewhere to receive the contact records. To be really paranoid, Gerrit always ships the data to another HTTP server, preferably over HTTPS. Existing open-source server implementations can be found in the gerrit-contactstore project.
'$site_path'/etc/gerrit.config with the contact store’s
contactstore.url), and if needed, APPSEC value (in
git config --file $site_path/etc/gerrit.config appsec.url https://... git config --file $site_path/etc/gerrit.config appsec.appsec sekret
Contact Store Protocol
To implement a new contact store, the following details are useful.
Gerrit connects to the contact store by sending a standard
application/x-www-form-urlencoded within an HTTP POST request
sent to the store URL (the exact URL that is in contactstore.url)
with the following form fields in the body:
A shared secret "password" that should be known only to Gerrit and the contact store. The contact store should test this value to deter spamming of the contact store by outside parties. Gerrit reads this from contactstore.appsec.
Unique account_id value from the Gerrit database for the account the contact information belongs to. Base 10 integer.
Preferred email address of the account. May facilitate lookups in the contact store at a future date. May be omitted or the empty string if the user hasn’t chosen a preferred email.
Seconds since the UNIX epoch of when the contact information was filed. May be omitted or the empty string if Gerrit doesn’t think the supplied contact information is valid enough.
Encrypted account data as an armored ASCII blob. This is usually several KB of text data as a single string, with embedded newlines to break the lines at about 70-75 characters per line. Data can be decoded using GnuPG with the correct private key.
Upon successful store, the contact store application should respond
with HTTP status code
200 and a body consisting only of
OK\n). Any other response code or body is considered to be
a failure by Gerrit.
https:// for the store URL is highly encouraged, as it
prevents man-in-the-middle attacks from reading the shared secret
APPSEC token, or messing with the data field.
Once decrypted the
data field looks something like the following:
Account-Id: 1001240 Date: 2009-02-23 20:32:32.852 UTC Full-Name: John Doe Preferred-Email: email@example.com Identity: firstname.lastname@example.org Identity: email@example.com <https://www.google.com/accounts/o8/id?id=AIt18axxafvda821aQZaHDF1k8akbalk218sak> Identity: firstname.lastname@example.org <http://jdoe.blogger.com/> Address: 123 Any Street Any Town, Somewhere Country: USA Phone-Number: +1 (555) 555-1212 Fax-Number: 555.1200
The fields are as follows:
Value of the
account_idfield in the metadata database. This is a unique key for this account, and links all data records to it.
Date and time of when this contact record was submitted by the user. Written in an ISO formatted date/time string (
YYYY-MM-DD hh:mm:ss), in the UTC timezone.
full_namefield of the account record when the user submitted the contact information. This should be the user’s given name and family name.
preferred_emailfield of the account record when the user submitted the contact information. This should be one of the emails listed in the
This field occurs once for each
account_external_idrecord in the database for this account. The email address is listed, and if the user is using OpenID authentication, the OpenID claimed identity follows in brackets (
<...>). Identity lines without an OpenID identity are usually created by sending an email containing a unique hyperlink that the user must visit to setup the identity.
Free form text, as entered by the user. This should describe some location that physical documents could be sent to, but it is not verified, so users can enter pretty much anything here. Each line is prefixed with a single TAB character, but is otherwise exactly as entered.
Free form text, as entered by the user. This should be some sort of country name or ISO country abbreviation, but it is not verified, so it can be pretty much anything.
Free form text, as entered by the user. The format here can be anything, and as the example shows, may not even be consistent in the same record.
Part of Gerrit Code Review