Import code from internal repository to git

This commit is contained in:
Justine Tunney 2016-03-01 17:18:14 -05:00
commit 0ef0c933d2
2490 changed files with 281594 additions and 0 deletions

View file

@ -0,0 +1,16 @@
package(
default_visibility = ["//java/com/google/domain/registry:registry_project"],
)
java_library(
name = "api",
srcs = glob(["*.java"]),
deps = [
"//java/com/google/common/base",
"//third_party/java/bouncycastle",
"//third_party/java/bouncycastle_bcpg",
"//third_party/java/dagger",
"//third_party/java/jsr305_annotations",
],
)

View file

@ -0,0 +1,133 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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.domain.registry.keyring.api;
import static com.google.common.base.Strings.emptyToNull;
import com.google.common.base.Optional;
import dagger.Module;
import dagger.Provides;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import java.lang.annotation.Documented;
import javax.inject.Qualifier;
/** Dagger module for keys stored in {@link Keyring}. */
@Module
public final class KeyModule {
/** Dagger qualifier for keys from {@link Keyring}. */
@Qualifier
@Documented
public static @interface Key {
String value();
}
@Provides
@Key("brdaReceiverKey")
static PGPPublicKey provideBrdaReceiverKey(Keyring keyring) {
return keyring.getBrdaReceiverKey();
}
@Provides
@Key("brdaSigningKey")
static PGPKeyPair provideBrdaSigningKey(Keyring keyring) {
return keyring.getBrdaSigningKey();
}
@Provides
@Key("icannReportingPassword")
static String provideIcannReportingPassword(Keyring keyring) {
return keyring.getIcannReportingPassword();
}
@Provides
@Key("marksdbDnlLogin")
static Optional<String> provideMarksdbDnlLogin(Keyring keyring) {
return Optional.fromNullable(emptyToNull(keyring.getMarksdbDnlLogin()));
}
@Provides
@Key("marksdbLordnPassword")
static Optional<String> provideMarksdbLordnPassword(Keyring keyring) {
return Optional.fromNullable(emptyToNull(keyring.getMarksdbLordnPassword()));
}
@Provides
@Key("marksdbSmdrlLogin")
static Optional<String> provideMarksdbSmdrlLogin(Keyring keyring) {
return Optional.fromNullable(emptyToNull(keyring.getMarksdbSmdrlLogin()));
}
@Provides
@Key("rdeStagingEncryptionKey")
static PGPPublicKey provideRdeStagingEncryptionKey(Keyring keyring) {
return keyring.getRdeStagingEncryptionKey();
}
@Provides
@Key("rdeStagingEncryptionKey")
static byte[] provideRdeStagingEncryptionKeyAsBytes(
@Key("rdeStagingEncryptionKey") PGPPublicKey rdeStagingEncryptionKey) {
return PgpHelper.convertPublicKeyToBytes(rdeStagingEncryptionKey);
}
@Provides
@Key("rdeStagingDecryptionKey")
static PGPPrivateKey provideRdeStagingDecryptionKey(Keyring keyring) {
return keyring.getRdeStagingDecryptionKey();
}
@Provides
@Key("rdeReceiverKey")
static PGPPublicKey provideRdeReceiverKey(Keyring keyring) {
return keyring.getRdeReceiverKey();
}
@Provides
@Key("rdeSigningKey")
static PGPKeyPair provideRdeSigningKey(Keyring keyring) {
return keyring.getRdeSigningKey();
}
@Provides
@Key("rdeSshClientPrivateKey")
static String provideRdeSshClientPrivateKey(Keyring keyring) {
return keyring.getRdeSshClientPrivateKey();
}
@Provides
@Key("rdeSshClientPublicKey")
static String provideRdeSshClientPublicKey(Keyring keyring) {
return keyring.getRdeSshClientPublicKey();
}
@Provides
@Key("jsonCredential")
static String provideJsonCredential(Keyring keyring) {
return keyring.getJsonCredential();
}
@Provides
@Key("braintreePrivateKey")
static String provideBraintreePrivateKey(Keyring keyring) {
return keyring.getBraintreePrivateKey();
}
}

View file

@ -0,0 +1,165 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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.domain.registry.keyring.api;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import javax.annotation.concurrent.ThreadSafe;
/**
* Domain Registry keyring interface.
*
* <p>Separate methods are defined for each specific situation in which the
* registry server needs a secret value, like a PGP key or password.
*/
@ThreadSafe
public interface Keyring extends AutoCloseable {
/**
* Returns the key which should be used to sign RDE deposits being uploaded to a third-party.
*
* <p>When we give all our data to the escrow provider, they'll need
* a signature to ensure the data is authentic.
*
* <p>This keypair should only be known to the domain registry shared
* registry system.
*
* @see com.google.domain.registry.rde.RdeUploadTask
*/
PGPKeyPair getRdeSigningKey();
/**
* Returns public key for encrypting escrow deposits being staged to cloud storage.
*
* <p>This adds an additional layer of security so cloud storage administrators
* won't be tempted to go poking around the App Engine Cloud Console and see a
* dump of the entire database.
*
* <p>This keypair should only be known to the domain registry shared
* registry system.
*
* @see #getRdeStagingDecryptionKey()
*/
PGPPublicKey getRdeStagingEncryptionKey();
/**
* Returns private key for decrypting escrow deposits retrieved from cloud storage.
*
* <p>This method may impose restrictions on who can call it. For example, we'd want
* to check that the caller isn't an HTTP request attacking a vulnerability in the
* admin console. The request should originate from a backend task queue servlet
* invocation of the RDE upload thing.
*
* @see #getRdeStagingEncryptionKey()
* @see com.google.domain.registry.rde.RdeUploadTask
*/
PGPPrivateKey getRdeStagingDecryptionKey();
/**
* Returns public key of escrow agent for encrypting deposits as they're uploaded.
*
* @see com.google.domain.registry.rde.RdeUploadTask
*/
PGPPublicKey getRdeReceiverKey();
/**
* Returns the PGP key we use to sign Bulk Registration Data Access (BRDA) deposits.
*
* @see com.google.domain.registry.rde.BrdaCopyTask
*/
PGPKeyPair getBrdaSigningKey();
/**
* Returns public key of receiver of Bulk Registration Data Access (BRDA) deposits.
*
* @see com.google.domain.registry.rde.BrdaCopyTask
*/
PGPPublicKey getBrdaReceiverKey();
/**
* Returns public key for SSH client connections made by RDE.
*
* <p>This is a string containing what would otherwise be the contents of an
* {@code ~/.ssh/id_rsa.pub} file. It's usually a single line with the name of
* the algorithm, the base64 key, and the email address of the owner.
*
* @see com.google.domain.registry.rde.RdeUploadTask
*/
String getRdeSshClientPublicKey();
/**
* Returns private key for SSH client connections made by RDE.
*
* <p>This is a string containing what would otherwise be the contents of an
* {@code ~/.ssh/id_rsa} file. It's ASCII-armored text.
*
* <p>This method may impose restrictions on who can call it. For example, we'd want
* to check that the caller isn't an HTTP request attacking a vulnerability in the
* admin console. The request should originate from a backend task queue servlet
* invocation of the RDE upload thing.
*
* @see com.google.domain.registry.rde.RdeUploadTask
*/
String getRdeSshClientPrivateKey();
/**
* Returns password to be used when uploading reports to ICANN.
*
* @see com.google.domain.registry.rde.RdeReportTask
*/
String getIcannReportingPassword();
/**
* Returns {@code user:password} login for TMCH MarksDB HTTP server DNL interface.
*
* @see com.google.domain.registry.tmch.TmchDnlTask
*/
String getMarksdbDnlLogin();
/**
* Returns password for TMCH MarksDB HTTP server LORDN interface.
*
* @see "com.google.domain.registry.tmch.LordnRequestInitializer"
*/
String getMarksdbLordnPassword();
/**
* Returns {@code user:password} login for TMCH MarksDB HTTP server SMDRL interface.
*
* @see com.google.domain.registry.tmch.TmchSmdrlTask
*/
String getMarksdbSmdrlLogin();
/**
* Returns the credentials for a service account on the Google AppEngine project downloaded from
* the Cloud Console dashboard in JSON format.
*/
String getJsonCredential();
/**
* Returns Braintree API private key for Registry.
*
* <p>This is a base32 value copied from the Braintree website.
*
* @see com.google.domain.registry.config.ConfigModule#provideBraintreePublicKey
*/
String getBraintreePrivateKey();
// Don't throw so try-with-resources works better.
@Override
void close();
}

View file

@ -0,0 +1,176 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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.domain.registry.keyring.api;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Verify.verify;
import static com.google.common.base.Verify.verifyNotNull;
import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.DSA;
import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.ELGAMAL_GENERAL;
import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.RSA_GENERAL;
import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.RSA_SIGN;
import com.google.common.base.Optional;
import com.google.common.base.VerifyException;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.bc.BcPGPPublicKeyRing;
import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
import java.io.IOException;
import java.util.Iterator;
/** Helper functions for extracting PGP keys from their keyrings. */
public final class PgpHelper {
/**
* Narrowed key search requirements.
* @see PgpHelper#lookupPublicKey
*/
public static enum KeyRequirement { ENCRYPT, SIGN, ENCRYPT_SIGN }
/** Converts {@code publicKey} to bytes. */
public static byte[] convertPublicKeyToBytes(PGPPublicKey publicKey) {
try {
return publicKey.getEncoded();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/** Returns raw key bytes as a Bouncy Castle PGP public key. */
public static PGPPublicKey loadPublicKeyBytes(byte[] data) {
try {
return lookupPublicSubkey(new BcPGPPublicKeyRing(data), KeyRequirement.ENCRYPT).get();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Search for public key on keyring based on a substring (like an email address).
*
* @throws VerifyException if the key couldn't be found.
* @see #lookupKeyPair
*/
public static PGPPublicKey lookupPublicKey(
PGPPublicKeyRingCollection keyring, String query, KeyRequirement want) {
try {
// Safe by specification.
@SuppressWarnings("unchecked")
Iterator<PGPPublicKeyRing> results =
keyring.getKeyRings(checkNotNull(query, "query"), true, true);
verify(results.hasNext(), "No public key found matching substring: %s", query);
while (results.hasNext()) {
Optional<PGPPublicKey> result = lookupPublicSubkey(results.next(), want);
if (result.isPresent()) {
return result.get();
}
}
throw new VerifyException(String.format(
"No public key (%s) found matching substring: %s", want, query));
} catch (PGPException e) {
throw new VerifyException(String.format(
"Public key lookup with query %s failed: %s", query, e.getMessage()));
}
}
/**
* Same as {@link #lookupPublicKey} but also retrieves the associated private key.
*
* @throws VerifyException if either keys couldn't be found.
* @see #lookupPublicKey
*/
@SuppressWarnings("deprecation")
public static PGPKeyPair lookupKeyPair(
PGPPublicKeyRingCollection publics,
PGPSecretKeyRingCollection privates,
String query,
KeyRequirement want) {
PGPPublicKey publicKey = lookupPublicKey(publics, query, want);
PGPPrivateKey privateKey;
try {
PGPSecretKey secret = verifyNotNull(privates.getSecretKey(publicKey.getKeyID()),
"Keyring missing private key associated with public key id: %x (query '%s')",
publicKey.getKeyID(), query);
// We do not support putting a password on the private key so we're just going to
// put char[0] here.
privateKey = secret.extractPrivateKey(
new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider())
.build(new char[0]));
} catch (PGPException e) {
throw new VerifyException(e.getMessage());
}
return new PGPKeyPair(publicKey, privateKey);
}
/**
* Return appropriate key or subkey for given task from public key.
*
* <p>Weirder older PGP public keys will actually have multiple keys. The main key will usually
* be sign-only in such situations. So you've gotta go digging in through the key packets and
* make sure you get the one that's valid for encryption, or whatever you want to do.
*/
public static Optional<PGPPublicKey> lookupPublicSubkey(
PGPPublicKeyRing ring, KeyRequirement want) {
// Safe by specification.
@SuppressWarnings("unchecked")
Iterator<PGPPublicKey> keys = ring.getPublicKeys();
while (keys.hasNext()) {
PGPPublicKey key = keys.next();
switch (want) {
case ENCRYPT:
if (key.isEncryptionKey()) {
return Optional.of(key);
}
break;
case SIGN:
if (isSigningKey(key)) {
return Optional.of(key);
}
break;
case ENCRYPT_SIGN:
if (key.isEncryptionKey() && isSigningKey(key)) {
return Optional.of(key);
}
break;
default:
throw new AssertionError();
}
}
return Optional.absent();
}
/** Returns {@code true} if this key can be used for signing. */
public static boolean isSigningKey(PGPPublicKey key) {
switch (key.getAlgorithm()) {
case RSA_GENERAL:
case RSA_SIGN:
case DSA:
case ELGAMAL_GENERAL:
return true;
default:
return false;
}
}
}

View file

@ -0,0 +1,116 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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.domain.registry.keyring.api;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import javax.annotation.concurrent.Immutable;
/** {@link Keyring} that throws {@link UnsupportedOperationException} if any methods are called. */
@Immutable
public final class VoidKeyring implements Keyring {
private static final String ERROR = "Keyring support not loaded";
/** @throws UnsupportedOperationException always */
@Override
public PGPKeyPair getRdeSigningKey() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public PGPKeyPair getBrdaSigningKey() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public PGPPublicKey getRdeStagingEncryptionKey() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public PGPPrivateKey getRdeStagingDecryptionKey() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public PGPPublicKey getRdeReceiverKey() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public PGPPublicKey getBrdaReceiverKey() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public String getRdeSshClientPublicKey() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public String getRdeSshClientPrivateKey() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public String getIcannReportingPassword() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public String getMarksdbDnlLogin() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public String getMarksdbLordnPassword() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public String getMarksdbSmdrlLogin() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public String getJsonCredential() {
throw new UnsupportedOperationException(ERROR);
}
/** @throws UnsupportedOperationException always */
@Override
public String getBraintreePrivateKey() {
throw new UnsupportedOperationException(ERROR);
}
/** Does nothing. */
@Override
public void close() {}
}

View file

@ -0,0 +1,32 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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.domain.registry.keyring.api;
import dagger.Module;
import dagger.Provides;
import javax.annotation.concurrent.Immutable;
/** Dagger keyring module that always returns {@link VoidKeyring} instances. */
@Module
@Immutable
public final class VoidKeyringModule {
/** Always returns a {@link VoidKeyring} instance. */
@Provides
static Keyring provideKeyring() {
return new VoidKeyring();
}
}

View file

@ -0,0 +1,16 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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.
@javax.annotation.ParametersAreNonnullByDefault
package com.google.domain.registry.keyring.api;