| Gerrit2 - Contact Information |
| ============================= |
| |
| 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 |
| and the `contactstore.url` setting in `gerrit.config` is not set, |
| Gerrit will not collect contact information from users. |
| |
| |
| Setup |
| ----- |
| |
| Ensure Bouncy Castle Crypto API is available in the web application's |
| CLASSPATH (e.g. in `'JETTY_HOME'/lib/plus` for Jetty). Gerrit needs |
| both `bcprov-jdk\*-*.jar` and `bcpg-jdk\*-*.jar` to be provided |
| for the contact encryption to work. |
| |
| * link:http://www.bouncycastle.org/latest_releases.html[Bouncy Castle Crypto API] |
| |
| 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. |
| |
| * link:http://java.sun.com/javase/downloads/index.jsp[Java SE Downloads] |
| |
| 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. |
| |
| ==== |
| gpg --gen-key |
| ==== |
| |
| 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. |
| |
| Chose 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 `contact_information.pub` |
| 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/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, preferrably over HTTPS. |
| Existing open-source server implementations can be found in the |
| gerrit-contactstore project. |
| |
| * link:http://android.git.kernel.org/?p=tools/gerrit-contactstore.git[gerrit-contactstore] |
| |
| Configure `'$site_path'/gerrit.config` with the contact store's |
| URL (in `contactstore.url`), and if needed, APPSEC value (in |
| `contactstore.appsec`): |
| |
| ==== |
| git config --file $site_path/gerrit.config appsec.url https://... |
| git config --file $site_path/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: |
| |
| * APPSEC |
| + |
| 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. |
| |
| * account_id |
| + |
| Unique account_id value from the Gerrit database for the account |
| the contact information belongs to. Base 10 integer. |
| |
| * email |
| + |
| 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. |
| |
| * filed |
| + |
| 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. |
| |
| * data |
| + |
| 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` |
| (or `OK\n`). Any other response code or body is considered to be |
| a failure by Gerrit. |
| |
| Using `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. |
| |
| Data Format |
| ~~~~~~~~~~~ |
| |
| 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: jdoe@example.com |
| Identity: jd15@some-isp.com |
| Identity: jdoe@example.com <https://www.google.com/accounts/o8/id?id=AIt18axxafvda821aQZaHDF1k8akbalk218sak> |
| Identity: jdoe@example.com <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: |
| |
| * `Account-Id` |
| + |
| Value of the `account_id` field in the metadata database. This is |
| a unique key for this account, and links all data records to it. |
| |
| * `Date` |
| + |
| 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-Name` |
| + |
| The `full_name` field of the account record when the user submitted |
| the contact information. This should be the user's given name and |
| family name. |
| |
| * `Preferred-Email` |
| + |
| The `preferred_email` field of the account record when the user |
| submitted the contact information. This should be one of the emails |
| listed in the `Identity` field. |
| |
| * `Identity` |
| + |
| This field occurs once for each `account_external_id` record |
| 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. |
| |
| * `Address` |
| + |
| 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. |
| |
| * `Country` |
| + |
| 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. |
| |
| * `Phone-Number`, `Fax-Number` |
| + |
| 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. |
| |
| GERRIT |
| ------ |
| Part of link:index.html[Gerrit Code Review] |