mirror of
https://github.com/google/nomulus.git
synced 2025-04-30 12:07:51 +02:00
Remove Cloud KMS from Nomulus Server (#1839)
* Remove Cloud KMS from Nomulus Server Removed Cloud KMS from the Nomulus (:core) since it is no longer used. Renamed remaining classes to reflect their use of the SecretManager. Updated the config instructions to use a new codename for the keyring: KMS to CSM. This PR works with both codenames. Will drop 'KMS' after the internal repo is updated.
This commit is contained in:
parent
2812df303d
commit
242864d198
32 changed files with 161 additions and 911 deletions
|
@ -186,7 +186,6 @@ dependencies {
|
||||||
implementation deps['com.google.apis:google-api-services-admin-directory']
|
implementation deps['com.google.apis:google-api-services-admin-directory']
|
||||||
implementation deps['com.google.apis:google-api-services-appengine']
|
implementation deps['com.google.apis:google-api-services-appengine']
|
||||||
implementation deps['com.google.apis:google-api-services-bigquery']
|
implementation deps['com.google.apis:google-api-services-bigquery']
|
||||||
implementation deps['com.google.apis:google-api-services-cloudkms']
|
|
||||||
implementation deps['com.google.apis:google-api-services-dataflow']
|
implementation deps['com.google.apis:google-api-services-dataflow']
|
||||||
implementation deps['com.google.apis:google-api-services-dns']
|
implementation deps['com.google.apis:google-api-services-dns']
|
||||||
implementation deps['com.google.apis:google-api-services-drive']
|
implementation deps['com.google.apis:google-api-services-drive']
|
||||||
|
|
|
@ -77,7 +77,6 @@ com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0=c
|
||||||
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-cloudkms:v1-rev20220701-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
|
||||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
|
|
|
@ -1076,24 +1076,6 @@ public final class RegistryConfig {
|
||||||
return config.keyring.activeKeyring;
|
return config.keyring.activeKeyring;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The name to use for the Cloud KMS KeyRing containing encryption keys for Nomulus secrets.
|
|
||||||
*
|
|
||||||
* @see <a
|
|
||||||
* href="https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings#KeyRing">projects.locations.keyRings</a>
|
|
||||||
*/
|
|
||||||
@Provides
|
|
||||||
@Config("cloudKmsKeyRing")
|
|
||||||
public static String provideCloudKmsKeyRing(RegistryConfigSettings config) {
|
|
||||||
return config.keyring.kms.keyringName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Config("cloudKmsProjectId")
|
|
||||||
public static String provideCloudKmsProjectId(RegistryConfigSettings config) {
|
|
||||||
return config.keyring.kms.projectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Config("customLogicFactoryClass")
|
@Config("customLogicFactoryClass")
|
||||||
public static String provideCustomLogicFactoryClass(RegistryConfigSettings config) {
|
public static String provideCustomLogicFactoryClass(RegistryConfigSettings config) {
|
||||||
|
|
|
@ -214,6 +214,7 @@ public class RegistryConfigSettings {
|
||||||
/** Configuration for keyrings (used to store secrets outside of source). */
|
/** Configuration for keyrings (used to store secrets outside of source). */
|
||||||
public static class Keyring {
|
public static class Keyring {
|
||||||
public String activeKeyring;
|
public String activeKeyring;
|
||||||
|
// TODO(b/257276342): Remove after config files in nomulus-internal are updated.
|
||||||
public Kms kms;
|
public Kms kms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -449,7 +449,8 @@ beam:
|
||||||
stagingBucketUrl: gcs-bucket-with-staged-templates
|
stagingBucketUrl: gcs-bucket-with-staged-templates
|
||||||
|
|
||||||
keyring:
|
keyring:
|
||||||
# The name of the active keyring, either "KMS" or "Dummy".
|
# The name of the active keyring, either "Dummy" or "CSM". The latter stands
|
||||||
|
# for Cloud SecretManager.
|
||||||
activeKeyring: Dummy
|
activeKeyring: Dummy
|
||||||
|
|
||||||
# Configuration options specific to Google Cloud KMS.
|
# Configuration options specific to Google Cloud KMS.
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
// Copyright 2017 The Nomulus Authors. 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 google.registry.keyring.kms;
|
|
||||||
|
|
||||||
import com.google.auto.value.AutoValue;
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A value type class containing a Cloud KMS encrypted and encoded ciphertext, and the name of the
|
|
||||||
* CryptoKeyVersion used to encrypt it.
|
|
||||||
*/
|
|
||||||
@AutoValue
|
|
||||||
abstract class EncryptResponse {
|
|
||||||
|
|
||||||
static EncryptResponse create(
|
|
||||||
com.google.api.services.cloudkms.v1.model.EncryptResponse cloudKmsEncryptResponse) {
|
|
||||||
return new AutoValue_EncryptResponse(
|
|
||||||
cloudKmsEncryptResponse.getCiphertext(), cloudKmsEncryptResponse.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
static EncryptResponse create(String ciphertext, String cryptoKeyVersionName) {
|
|
||||||
return new AutoValue_EncryptResponse(ciphertext, cryptoKeyVersionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract String ciphertext();
|
|
||||||
|
|
||||||
abstract String cryptoKeyVersionName();
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
// Copyright 2017 The Nomulus Authors. 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 google.registry.keyring.kms;
|
|
||||||
|
|
||||||
import google.registry.keyring.api.KeyringException;
|
|
||||||
|
|
||||||
/** An abstraction to simplify Cloud KMS operations. */
|
|
||||||
public interface KmsConnection {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum allowable secret size, as set by Cloud KMS.
|
|
||||||
*
|
|
||||||
* @see <a
|
|
||||||
* href="https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys/encrypt#request-body">projects.locations.keyRings.cryptoKeys.encrypt</a>
|
|
||||||
*/
|
|
||||||
int MAX_SECRET_SIZE_BYTES = 64 * 1024;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encrypts a plaintext with CryptoKey {@code cryptoKeyName} on KeyRing {@code keyRingName}.
|
|
||||||
*
|
|
||||||
* <p>The latest CryptoKeyVersion is used to encrypt the value. The value must not be larger than
|
|
||||||
* {@code MAX_SECRET_SIZE_BYTES}.
|
|
||||||
*
|
|
||||||
* <p>If no applicable CryptoKey or CryptoKeyVersion exist, they will be created.
|
|
||||||
*
|
|
||||||
* @throws KeyringException on encryption failure.
|
|
||||||
*/
|
|
||||||
EncryptResponse encrypt(String cryptoKeyName, byte[] plaintext);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decrypts a Cloud KMS encrypted and encoded value with CryptoKey {@code cryptoKeyName}.
|
|
||||||
*
|
|
||||||
* @throws KeyringException on decryption failure.
|
|
||||||
*/
|
|
||||||
byte[] decrypt(String cryptoKeyName, String encodedCiphertext);
|
|
||||||
}
|
|
|
@ -1,177 +0,0 @@
|
||||||
// Copyright 2017 The Nomulus Authors. 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 google.registry.keyring.kms;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
|
|
||||||
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
|
|
||||||
import com.google.api.client.http.HttpStatusCodes;
|
|
||||||
import com.google.api.services.cloudkms.v1.CloudKMS;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.CryptoKey;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.CryptoKeyVersion;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.DecryptRequest;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.EncryptRequest;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.KeyRing;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.UpdateCryptoKeyPrimaryVersionRequest;
|
|
||||||
import google.registry.keyring.api.KeyringException;
|
|
||||||
import google.registry.util.Retrier;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/** The {@link KmsConnection} which talks to Cloud KMS. */
|
|
||||||
class KmsConnectionImpl implements KmsConnection {
|
|
||||||
|
|
||||||
private static final String KMS_LOCATION_FORMAT = "projects/%s/locations/global";
|
|
||||||
private static final String KMS_KEYRING_NAME_FORMAT = "projects/%s/locations/global/keyRings/%s";
|
|
||||||
private static final String KMS_CRYPTO_KEY_NAME_FORMAT =
|
|
||||||
"projects/%s/locations/global/keyRings/%s/cryptoKeys/%s";
|
|
||||||
|
|
||||||
private final CloudKMS kms;
|
|
||||||
private final String kmsKeyRingName;
|
|
||||||
private final String projectId;
|
|
||||||
private final Retrier retrier;
|
|
||||||
|
|
||||||
KmsConnectionImpl(String projectId, String kmsKeyRingName, Retrier retrier, CloudKMS kms) {
|
|
||||||
this.projectId = projectId;
|
|
||||||
this.kmsKeyRingName = kmsKeyRingName;
|
|
||||||
this.retrier = retrier;
|
|
||||||
this.kms = kms;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EncryptResponse encrypt(String cryptoKeyName, byte[] value) {
|
|
||||||
checkArgument(
|
|
||||||
value.length <= MAX_SECRET_SIZE_BYTES,
|
|
||||||
"Value to encrypt was larger than %s bytes",
|
|
||||||
MAX_SECRET_SIZE_BYTES);
|
|
||||||
try {
|
|
||||||
return attemptEncrypt(cryptoKeyName, value);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new KeyringException(
|
|
||||||
String.format("CloudKMS encrypt operation failed for secret %s", cryptoKeyName), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private EncryptResponse attemptEncrypt(String cryptoKeyName, byte[] value) throws IOException {
|
|
||||||
String fullKeyRingName = getKeyRingName(projectId, kmsKeyRingName);
|
|
||||||
try {
|
|
||||||
kms.projects().locations().keyRings().get(fullKeyRingName).execute();
|
|
||||||
} catch (GoogleJsonResponseException jsonException) {
|
|
||||||
if (jsonException.getStatusCode() == HttpStatusCodes.STATUS_CODE_NOT_FOUND) {
|
|
||||||
// Create the KeyRing in the "global" namespace. Encryption keys will be accessible from all
|
|
||||||
// GCP regions.
|
|
||||||
kms.projects()
|
|
||||||
.locations()
|
|
||||||
.keyRings()
|
|
||||||
.create(getLocationName(projectId), new KeyRing())
|
|
||||||
.setKeyRingId(kmsKeyRingName)
|
|
||||||
.execute();
|
|
||||||
} else {
|
|
||||||
throw jsonException;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String fullKeyName = getCryptoKeyName(projectId, kmsKeyRingName, cryptoKeyName);
|
|
||||||
|
|
||||||
boolean newCryptoKey = false;
|
|
||||||
try {
|
|
||||||
kms.projects().locations().keyRings().cryptoKeys().get(fullKeyName).execute();
|
|
||||||
} catch (GoogleJsonResponseException jsonException) {
|
|
||||||
if (jsonException.getStatusCode() == HttpStatusCodes.STATUS_CODE_NOT_FOUND) {
|
|
||||||
newCryptoKey = true;
|
|
||||||
kms.projects()
|
|
||||||
.locations()
|
|
||||||
.keyRings()
|
|
||||||
.cryptoKeys()
|
|
||||||
.create(fullKeyRingName, new CryptoKey().setPurpose("ENCRYPT_DECRYPT"))
|
|
||||||
.setCryptoKeyId(cryptoKeyName)
|
|
||||||
.execute();
|
|
||||||
} else {
|
|
||||||
throw jsonException;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// New CryptoKeys start with a CryptoKeyVersion, so we only create a new CryptoKeyVersion and
|
|
||||||
// rotate to it if we're dealing with an existing CryptoKey.
|
|
||||||
if (!newCryptoKey) {
|
|
||||||
CryptoKeyVersion cryptoKeyVersion =
|
|
||||||
kms.projects()
|
|
||||||
.locations()
|
|
||||||
.keyRings()
|
|
||||||
.cryptoKeys()
|
|
||||||
.cryptoKeyVersions()
|
|
||||||
.create(fullKeyName, new CryptoKeyVersion())
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
kms.projects()
|
|
||||||
.locations()
|
|
||||||
.keyRings()
|
|
||||||
.cryptoKeys()
|
|
||||||
.updatePrimaryVersion(
|
|
||||||
fullKeyName,
|
|
||||||
new UpdateCryptoKeyPrimaryVersionRequest()
|
|
||||||
.setCryptoKeyVersionId(getCryptoKeyVersionId(cryptoKeyVersion)))
|
|
||||||
.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
return EncryptResponse.create(
|
|
||||||
kms.projects()
|
|
||||||
.locations()
|
|
||||||
.keyRings()
|
|
||||||
.cryptoKeys()
|
|
||||||
.encrypt(fullKeyName, new EncryptRequest().encodePlaintext(value))
|
|
||||||
.execute());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] decrypt(final String cryptoKeyName, final String encodedCiphertext) {
|
|
||||||
try {
|
|
||||||
return retrier.callWithRetry(
|
|
||||||
() -> attemptDecrypt(cryptoKeyName, encodedCiphertext), IOException.class);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
throw new KeyringException(
|
|
||||||
String.format("CloudKMS decrypt operation failed for secret %s", cryptoKeyName), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] attemptDecrypt(String cryptoKeyName, String encodedCiphertext) throws IOException {
|
|
||||||
return kms.projects()
|
|
||||||
.locations()
|
|
||||||
.keyRings()
|
|
||||||
.cryptoKeys()
|
|
||||||
.decrypt(
|
|
||||||
getCryptoKeyName(projectId, kmsKeyRingName, cryptoKeyName),
|
|
||||||
new DecryptRequest().setCiphertext(encodedCiphertext))
|
|
||||||
.execute()
|
|
||||||
.decodePlaintext();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getLocationName(String projectId) {
|
|
||||||
return String.format(KMS_LOCATION_FORMAT, projectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getKeyRingName(String projectId, String kmsKeyRingName) {
|
|
||||||
return String.format(KMS_KEYRING_NAME_FORMAT, projectId, kmsKeyRingName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getCryptoKeyName(
|
|
||||||
String projectId, String kmsKeyRingName, String cryptoKeyName) {
|
|
||||||
return String.format(KMS_CRYPTO_KEY_NAME_FORMAT, projectId, kmsKeyRingName, cryptoKeyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getCryptoKeyVersionId(CryptoKeyVersion cryptoKeyVersion) {
|
|
||||||
String cryptoKeyVersionName = cryptoKeyVersion.getName();
|
|
||||||
return cryptoKeyVersionName.substring(cryptoKeyVersionName.lastIndexOf('/') + 1);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
// Copyright 2017 The Nomulus Authors. 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 google.registry.keyring.kms;
|
|
||||||
|
|
||||||
import com.google.api.services.cloudkms.v1.CloudKMS;
|
|
||||||
import dagger.Binds;
|
|
||||||
import dagger.Module;
|
|
||||||
import dagger.Provides;
|
|
||||||
import dagger.multibindings.IntoMap;
|
|
||||||
import dagger.multibindings.StringKey;
|
|
||||||
import google.registry.config.CredentialModule.DefaultCredential;
|
|
||||||
import google.registry.config.RegistryConfig.Config;
|
|
||||||
import google.registry.keyring.api.Keyring;
|
|
||||||
import google.registry.util.GoogleCredentialsBundle;
|
|
||||||
import google.registry.util.Retrier;
|
|
||||||
|
|
||||||
/** Dagger module for Cloud KMS. */
|
|
||||||
@Module
|
|
||||||
public abstract class KmsModule {
|
|
||||||
|
|
||||||
public static final String NAME = "KMS";
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Config("defaultKms")
|
|
||||||
static CloudKMS provideKms(
|
|
||||||
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
|
|
||||||
@Config("cloudKmsProjectId") String projectId) {
|
|
||||||
return createKms(credentialsBundle, projectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Config("beamKms")
|
|
||||||
static CloudKMS provideBeamKms(
|
|
||||||
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
|
|
||||||
@Config("beamCloudKmsProjectId") String projectId) {
|
|
||||||
return createKms(credentialsBundle, projectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CloudKMS createKms(GoogleCredentialsBundle credentialsBundle, String projectId) {
|
|
||||||
return new CloudKMS.Builder(
|
|
||||||
credentialsBundle.getHttpTransport(),
|
|
||||||
credentialsBundle.getJsonFactory(),
|
|
||||||
credentialsBundle.getHttpRequestInitializer())
|
|
||||||
.setApplicationName(projectId)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Config("defaultKmsConnection")
|
|
||||||
static KmsConnection provideKmsConnection(
|
|
||||||
@Config("cloudKmsProjectId") String projectId,
|
|
||||||
@Config("cloudKmsKeyRing") String keyringName,
|
|
||||||
Retrier retrier,
|
|
||||||
@Config("defaultKms") CloudKMS defaultKms) {
|
|
||||||
return new KmsConnectionImpl(projectId, keyringName, retrier, defaultKms);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Config("beamKmsConnection")
|
|
||||||
static KmsConnection provideBeamKmsConnection(
|
|
||||||
@Config("beamCloudKmsProjectId") String projectId,
|
|
||||||
@Config("beamCloudKmsKeyRing") String keyringName,
|
|
||||||
Retrier retrier,
|
|
||||||
@Config("beamKms") CloudKMS defaultKms) {
|
|
||||||
return new KmsConnectionImpl(projectId, keyringName, retrier, defaultKms);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Binds
|
|
||||||
@IntoMap
|
|
||||||
@StringKey(NAME)
|
|
||||||
abstract Keyring provideKeyring(KmsKeyring keyring);
|
|
||||||
}
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package google.registry.keyring.kms;
|
package google.registry.keyring.secretmanager;
|
||||||
|
|
||||||
import static com.google.common.base.CaseFormat.LOWER_HYPHEN;
|
import static com.google.common.base.CaseFormat.LOWER_HYPHEN;
|
||||||
import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
|
import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
|
||||||
|
@ -29,8 +29,7 @@ import org.bouncycastle.openpgp.PGPPrivateKey;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
|
|
||||||
/** A {@link Keyring} implementation which stores sensitive data in the Secret Manager. */
|
/** A {@link Keyring} implementation which stores sensitive data in the Secret Manager. */
|
||||||
// TODO(2021-08-01): rename this class to SecretManagerKeyring and update config files.
|
public class SecretManagerKeyring implements Keyring {
|
||||||
public class KmsKeyring implements Keyring {
|
|
||||||
|
|
||||||
/** Key labels for private key secrets. */
|
/** Key labels for private key secrets. */
|
||||||
enum PrivateKeyLabel {
|
enum PrivateKeyLabel {
|
||||||
|
@ -75,7 +74,7 @@ public class KmsKeyring implements Keyring {
|
||||||
private final KeyringSecretStore secretStore;
|
private final KeyringSecretStore secretStore;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
KmsKeyring(KeyringSecretStore secretStore) {
|
SecretManagerKeyring(KeyringSecretStore secretStore) {
|
||||||
this.secretStore = secretStore;
|
this.secretStore = secretStore;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2017 The Nomulus Authors. 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 google.registry.keyring.secretmanager;
|
||||||
|
|
||||||
|
import dagger.Binds;
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.multibindings.IntoMap;
|
||||||
|
import dagger.multibindings.StringKey;
|
||||||
|
import google.registry.keyring.api.Keyring;
|
||||||
|
|
||||||
|
/** Dagger module for {@link Keyring} backed by the Cloud SecretManager. */
|
||||||
|
@Module
|
||||||
|
public abstract class SecretManagerKeyringModule {
|
||||||
|
|
||||||
|
public static final String NAME = "CSM";
|
||||||
|
// TODO(b/257276342): Remove after configs in nomulus-internal are updated.
|
||||||
|
public static final String DEPRECATED_NAME = "KMS";
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@StringKey(DEPRECATED_NAME)
|
||||||
|
abstract Keyring provideDeprecatedKeyring(SecretManagerKeyring keyring);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@StringKey(NAME)
|
||||||
|
abstract Keyring provideKeyring(SecretManagerKeyring keyring);
|
||||||
|
}
|
|
@ -12,33 +12,33 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package google.registry.keyring.kms;
|
package google.registry.keyring.secretmanager;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel.BRDA_SIGNING_PRIVATE;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PrivateKeyLabel.BRDA_SIGNING_PRIVATE;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel.RDE_SIGNING_PRIVATE;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PrivateKeyLabel.RDE_SIGNING_PRIVATE;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel.RDE_STAGING_PRIVATE;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PrivateKeyLabel.RDE_STAGING_PRIVATE;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.BRDA_RECEIVER_PUBLIC;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.BRDA_RECEIVER_PUBLIC;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.BRDA_SIGNING_PUBLIC;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.BRDA_SIGNING_PUBLIC;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_RECEIVER_PUBLIC;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.RDE_RECEIVER_PUBLIC;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_SIGNING_PUBLIC;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.RDE_SIGNING_PUBLIC;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_STAGING_PUBLIC;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.RDE_STAGING_PUBLIC;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.ICANN_REPORTING_PASSWORD_STRING;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.ICANN_REPORTING_PASSWORD_STRING;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.JSON_CREDENTIAL_STRING;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.JSON_CREDENTIAL_STRING;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.MARKSDB_DNL_LOGIN_STRING;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.MARKSDB_DNL_LOGIN_STRING;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.MARKSDB_LORDN_PASSWORD_STRING;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.MARKSDB_LORDN_PASSWORD_STRING;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.MARKSDB_SMDRL_LOGIN_STRING;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.MARKSDB_SMDRL_LOGIN_STRING;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.RDE_SSH_CLIENT_PRIVATE_STRING;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.RDE_SSH_CLIENT_PRIVATE_STRING;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.RDE_SSH_CLIENT_PUBLIC_STRING;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.RDE_SSH_CLIENT_PUBLIC_STRING;
|
||||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.SAFE_BROWSING_API_KEY;
|
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.SAFE_BROWSING_API_KEY;
|
||||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||||
|
|
||||||
import com.google.common.flogger.FluentLogger;
|
import com.google.common.flogger.FluentLogger;
|
||||||
import google.registry.keyring.api.KeySerializer;
|
import google.registry.keyring.api.KeySerializer;
|
||||||
import google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel;
|
import google.registry.keyring.secretmanager.SecretManagerKeyring.PrivateKeyLabel;
|
||||||
import google.registry.keyring.kms.KmsKeyring.PublicKeyLabel;
|
import google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel;
|
||||||
import google.registry.keyring.kms.KmsKeyring.StringKeyLabel;
|
import google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel;
|
||||||
import google.registry.privileges.secretmanager.KeyringSecretStore;
|
import google.registry.privileges.secretmanager.KeyringSecretStore;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -50,73 +50,77 @@ import org.bouncycastle.openpgp.PGPKeyPair;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link KmsUpdater} accumulates updates to a {@link KmsKeyring} and persists them to KMS and
|
* The {@link SecretManagerKeyringUpdater} accumulates updates to a {@link SecretManagerKeyring} and
|
||||||
* Datastore when closed.
|
* persists them to KMS and Datastore when closed.
|
||||||
*/
|
*/
|
||||||
// TODO(2021-06-01): rename this class to SecretManagerKeyringUpdater
|
public final class SecretManagerKeyringUpdater {
|
||||||
public final class KmsUpdater {
|
|
||||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||||
|
|
||||||
private final KeyringSecretStore secretStore;
|
private final KeyringSecretStore secretStore;
|
||||||
private final HashMap<String, byte[]> secretValues;
|
private final HashMap<String, byte[]> secretValues;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public KmsUpdater(KeyringSecretStore secretStore) {
|
public SecretManagerKeyringUpdater(KeyringSecretStore secretStore) {
|
||||||
this.secretStore = secretStore;
|
this.secretStore = secretStore;
|
||||||
|
|
||||||
// Use LinkedHashMap to preserve insertion order on update() to simplify testing and debugging
|
// Use LinkedHashMap to preserve insertion order on update() to simplify testing and debugging
|
||||||
this.secretValues = new LinkedHashMap<>();
|
this.secretValues = new LinkedHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setRdeSigningKey(PGPKeyPair keyPair) throws IOException, PGPException {
|
public SecretManagerKeyringUpdater setRdeSigningKey(PGPKeyPair keyPair)
|
||||||
|
throws IOException, PGPException {
|
||||||
return setKeyPair(keyPair, RDE_SIGNING_PRIVATE, RDE_SIGNING_PUBLIC);
|
return setKeyPair(keyPair, RDE_SIGNING_PRIVATE, RDE_SIGNING_PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setRdeStagingKey(PGPKeyPair keyPair) throws IOException, PGPException {
|
public SecretManagerKeyringUpdater setRdeStagingKey(PGPKeyPair keyPair)
|
||||||
|
throws IOException, PGPException {
|
||||||
return setKeyPair(keyPair, RDE_STAGING_PRIVATE, RDE_STAGING_PUBLIC);
|
return setKeyPair(keyPair, RDE_STAGING_PRIVATE, RDE_STAGING_PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setRdeReceiverPublicKey(PGPPublicKey publicKey) throws IOException {
|
public SecretManagerKeyringUpdater setRdeReceiverPublicKey(PGPPublicKey publicKey)
|
||||||
|
throws IOException {
|
||||||
return setPublicKey(publicKey, RDE_RECEIVER_PUBLIC);
|
return setPublicKey(publicKey, RDE_RECEIVER_PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setBrdaSigningKey(PGPKeyPair keyPair) throws IOException, PGPException {
|
public SecretManagerKeyringUpdater setBrdaSigningKey(PGPKeyPair keyPair)
|
||||||
|
throws IOException, PGPException {
|
||||||
return setKeyPair(keyPair, BRDA_SIGNING_PRIVATE, BRDA_SIGNING_PUBLIC);
|
return setKeyPair(keyPair, BRDA_SIGNING_PRIVATE, BRDA_SIGNING_PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setBrdaReceiverPublicKey(PGPPublicKey publicKey) throws IOException {
|
public SecretManagerKeyringUpdater setBrdaReceiverPublicKey(PGPPublicKey publicKey)
|
||||||
|
throws IOException {
|
||||||
return setPublicKey(publicKey, BRDA_RECEIVER_PUBLIC);
|
return setPublicKey(publicKey, BRDA_RECEIVER_PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setRdeSshClientPublicKey(String asciiPublicKey) {
|
public SecretManagerKeyringUpdater setRdeSshClientPublicKey(String asciiPublicKey) {
|
||||||
return setString(asciiPublicKey, RDE_SSH_CLIENT_PUBLIC_STRING);
|
return setString(asciiPublicKey, RDE_SSH_CLIENT_PUBLIC_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setRdeSshClientPrivateKey(String asciiPrivateKey) {
|
public SecretManagerKeyringUpdater setRdeSshClientPrivateKey(String asciiPrivateKey) {
|
||||||
return setString(asciiPrivateKey, RDE_SSH_CLIENT_PRIVATE_STRING);
|
return setString(asciiPrivateKey, RDE_SSH_CLIENT_PRIVATE_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setSafeBrowsingAPIKey(String apiKey) {
|
public SecretManagerKeyringUpdater setSafeBrowsingAPIKey(String apiKey) {
|
||||||
return setString(apiKey, SAFE_BROWSING_API_KEY);
|
return setString(apiKey, SAFE_BROWSING_API_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setIcannReportingPassword(String password) {
|
public SecretManagerKeyringUpdater setIcannReportingPassword(String password) {
|
||||||
return setString(password, ICANN_REPORTING_PASSWORD_STRING);
|
return setString(password, ICANN_REPORTING_PASSWORD_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setMarksdbDnlLoginAndPassword(String login) {
|
public SecretManagerKeyringUpdater setMarksdbDnlLoginAndPassword(String login) {
|
||||||
return setString(login, MARKSDB_DNL_LOGIN_STRING);
|
return setString(login, MARKSDB_DNL_LOGIN_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setMarksdbLordnPassword(String password) {
|
public SecretManagerKeyringUpdater setMarksdbLordnPassword(String password) {
|
||||||
return setString(password, MARKSDB_LORDN_PASSWORD_STRING);
|
return setString(password, MARKSDB_LORDN_PASSWORD_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setMarksdbSmdrlLoginAndPassword(String login) {
|
public SecretManagerKeyringUpdater setMarksdbSmdrlLoginAndPassword(String login) {
|
||||||
return setString(login, MARKSDB_SMDRL_LOGIN_STRING);
|
return setString(login, MARKSDB_SMDRL_LOGIN_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KmsUpdater setJsonCredential(String credential) {
|
public SecretManagerKeyringUpdater setJsonCredential(String credential) {
|
||||||
return setString(credential, JSON_CREDENTIAL_STRING);
|
return setString(credential, JSON_CREDENTIAL_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,22 +148,22 @@ public final class KmsUpdater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private KmsUpdater setString(String key, StringKeyLabel stringKeyLabel) {
|
private SecretManagerKeyringUpdater setString(String key, StringKeyLabel stringKeyLabel) {
|
||||||
checkArgumentNotNull(key);
|
checkArgumentNotNull(key);
|
||||||
|
|
||||||
setSecret(stringKeyLabel.getLabel(), KeySerializer.serializeString(key));
|
setSecret(stringKeyLabel.getLabel(), KeySerializer.serializeString(key));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KmsUpdater setPublicKey(PGPPublicKey publicKey, PublicKeyLabel publicKeyLabel)
|
private SecretManagerKeyringUpdater setPublicKey(
|
||||||
throws IOException {
|
PGPPublicKey publicKey, PublicKeyLabel publicKeyLabel) throws IOException {
|
||||||
checkArgumentNotNull(publicKey);
|
checkArgumentNotNull(publicKey);
|
||||||
|
|
||||||
setSecret(publicKeyLabel.getLabel(), KeySerializer.serializePublicKey(publicKey));
|
setSecret(publicKeyLabel.getLabel(), KeySerializer.serializePublicKey(publicKey));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KmsUpdater setKeyPair(
|
private SecretManagerKeyringUpdater setKeyPair(
|
||||||
PGPKeyPair keyPair, PrivateKeyLabel privateKeyLabel, PublicKeyLabel publicKeyLabel)
|
PGPKeyPair keyPair, PrivateKeyLabel privateKeyLabel, PublicKeyLabel publicKeyLabel)
|
||||||
throws IOException, PGPException {
|
throws IOException, PGPException {
|
||||||
checkArgumentNotNull(keyPair);
|
checkArgumentNotNull(keyPair);
|
|
@ -33,7 +33,7 @@ import google.registry.groups.GroupssettingsModule;
|
||||||
import google.registry.keyring.KeyringModule;
|
import google.registry.keyring.KeyringModule;
|
||||||
import google.registry.keyring.api.DummyKeyringModule;
|
import google.registry.keyring.api.DummyKeyringModule;
|
||||||
import google.registry.keyring.api.KeyModule;
|
import google.registry.keyring.api.KeyModule;
|
||||||
import google.registry.keyring.kms.KmsModule;
|
import google.registry.keyring.secretmanager.SecretManagerKeyringModule;
|
||||||
import google.registry.module.backend.BackendRequestComponent.BackendRequestComponentModule;
|
import google.registry.module.backend.BackendRequestComponent.BackendRequestComponentModule;
|
||||||
import google.registry.monitoring.whitebox.StackdriverModule;
|
import google.registry.monitoring.whitebox.StackdriverModule;
|
||||||
import google.registry.persistence.PersistenceModule;
|
import google.registry.persistence.PersistenceModule;
|
||||||
|
@ -70,9 +70,9 @@ import javax.inject.Singleton;
|
||||||
GsonModule.class,
|
GsonModule.class,
|
||||||
KeyModule.class,
|
KeyModule.class,
|
||||||
KeyringModule.class,
|
KeyringModule.class,
|
||||||
KmsModule.class,
|
|
||||||
NetHttpTransportModule.class,
|
NetHttpTransportModule.class,
|
||||||
PersistenceModule.class,
|
PersistenceModule.class,
|
||||||
|
SecretManagerKeyringModule.class,
|
||||||
SecretManagerModule.class,
|
SecretManagerModule.class,
|
||||||
ServerTridProviderModule.class,
|
ServerTridProviderModule.class,
|
||||||
SheetsServiceModule.class,
|
SheetsServiceModule.class,
|
||||||
|
|
|
@ -28,7 +28,7 @@ import google.registry.groups.GroupssettingsModule;
|
||||||
import google.registry.keyring.KeyringModule;
|
import google.registry.keyring.KeyringModule;
|
||||||
import google.registry.keyring.api.DummyKeyringModule;
|
import google.registry.keyring.api.DummyKeyringModule;
|
||||||
import google.registry.keyring.api.KeyModule;
|
import google.registry.keyring.api.KeyModule;
|
||||||
import google.registry.keyring.kms.KmsModule;
|
import google.registry.keyring.secretmanager.SecretManagerKeyringModule;
|
||||||
import google.registry.module.frontend.FrontendRequestComponent.FrontendRequestComponentModule;
|
import google.registry.module.frontend.FrontendRequestComponent.FrontendRequestComponentModule;
|
||||||
import google.registry.monitoring.whitebox.StackdriverModule;
|
import google.registry.monitoring.whitebox.StackdriverModule;
|
||||||
import google.registry.privileges.secretmanager.SecretManagerModule;
|
import google.registry.privileges.secretmanager.SecretManagerModule;
|
||||||
|
@ -59,8 +59,8 @@ import javax.inject.Singleton;
|
||||||
GsonModule.class,
|
GsonModule.class,
|
||||||
KeyModule.class,
|
KeyModule.class,
|
||||||
KeyringModule.class,
|
KeyringModule.class,
|
||||||
KmsModule.class,
|
|
||||||
NetHttpTransportModule.class,
|
NetHttpTransportModule.class,
|
||||||
|
SecretManagerKeyringModule.class,
|
||||||
SecretManagerModule.class,
|
SecretManagerModule.class,
|
||||||
ServerTridProviderModule.class,
|
ServerTridProviderModule.class,
|
||||||
StackdriverModule.class,
|
StackdriverModule.class,
|
||||||
|
|
|
@ -27,7 +27,7 @@ import google.registry.groups.GroupssettingsModule;
|
||||||
import google.registry.keyring.KeyringModule;
|
import google.registry.keyring.KeyringModule;
|
||||||
import google.registry.keyring.api.DummyKeyringModule;
|
import google.registry.keyring.api.DummyKeyringModule;
|
||||||
import google.registry.keyring.api.KeyModule;
|
import google.registry.keyring.api.KeyModule;
|
||||||
import google.registry.keyring.kms.KmsModule;
|
import google.registry.keyring.secretmanager.SecretManagerKeyringModule;
|
||||||
import google.registry.module.pubapi.PubApiRequestComponent.PubApiRequestComponentModule;
|
import google.registry.module.pubapi.PubApiRequestComponent.PubApiRequestComponentModule;
|
||||||
import google.registry.monitoring.whitebox.StackdriverModule;
|
import google.registry.monitoring.whitebox.StackdriverModule;
|
||||||
import google.registry.persistence.PersistenceModule;
|
import google.registry.persistence.PersistenceModule;
|
||||||
|
@ -54,10 +54,10 @@ import javax.inject.Singleton;
|
||||||
GsonModule.class,
|
GsonModule.class,
|
||||||
KeyModule.class,
|
KeyModule.class,
|
||||||
KeyringModule.class,
|
KeyringModule.class,
|
||||||
KmsModule.class,
|
|
||||||
NetHttpTransportModule.class,
|
NetHttpTransportModule.class,
|
||||||
PersistenceModule.class,
|
PersistenceModule.class,
|
||||||
PubApiRequestComponentModule.class,
|
PubApiRequestComponentModule.class,
|
||||||
|
SecretManagerKeyringModule.class,
|
||||||
SecretManagerModule.class,
|
SecretManagerModule.class,
|
||||||
ServerTridProviderModule.class,
|
ServerTridProviderModule.class,
|
||||||
StackdriverModule.class,
|
StackdriverModule.class,
|
||||||
|
|
|
@ -29,7 +29,7 @@ import google.registry.groups.GroupssettingsModule;
|
||||||
import google.registry.keyring.KeyringModule;
|
import google.registry.keyring.KeyringModule;
|
||||||
import google.registry.keyring.api.DummyKeyringModule;
|
import google.registry.keyring.api.DummyKeyringModule;
|
||||||
import google.registry.keyring.api.KeyModule;
|
import google.registry.keyring.api.KeyModule;
|
||||||
import google.registry.keyring.kms.KmsModule;
|
import google.registry.keyring.secretmanager.SecretManagerKeyringModule;
|
||||||
import google.registry.module.tools.ToolsRequestComponent.ToolsRequestComponentModule;
|
import google.registry.module.tools.ToolsRequestComponent.ToolsRequestComponentModule;
|
||||||
import google.registry.monitoring.whitebox.StackdriverModule;
|
import google.registry.monitoring.whitebox.StackdriverModule;
|
||||||
import google.registry.privileges.secretmanager.SecretManagerModule;
|
import google.registry.privileges.secretmanager.SecretManagerModule;
|
||||||
|
@ -57,8 +57,8 @@ import javax.inject.Singleton;
|
||||||
GsonModule.class,
|
GsonModule.class,
|
||||||
KeyModule.class,
|
KeyModule.class,
|
||||||
KeyringModule.class,
|
KeyringModule.class,
|
||||||
KmsModule.class,
|
|
||||||
NetHttpTransportModule.class,
|
NetHttpTransportModule.class,
|
||||||
|
SecretManagerKeyringModule.class,
|
||||||
SecretManagerModule.class,
|
SecretManagerModule.class,
|
||||||
ServerTridProviderModule.class,
|
ServerTridProviderModule.class,
|
||||||
StackdriverModule.class,
|
StackdriverModule.class,
|
||||||
|
|
|
@ -17,7 +17,7 @@ package google.registry.persistence;
|
||||||
import dagger.Component;
|
import dagger.Component;
|
||||||
import google.registry.config.CredentialModule;
|
import google.registry.config.CredentialModule;
|
||||||
import google.registry.config.RegistryConfig.ConfigModule;
|
import google.registry.config.RegistryConfig.ConfigModule;
|
||||||
import google.registry.keyring.kms.KmsModule;
|
import google.registry.keyring.secretmanager.SecretManagerKeyringModule;
|
||||||
import google.registry.persistence.PersistenceModule.AppEngineJpaTm;
|
import google.registry.persistence.PersistenceModule.AppEngineJpaTm;
|
||||||
import google.registry.persistence.PersistenceModule.ReadOnlyReplicaJpaTm;
|
import google.registry.persistence.PersistenceModule.ReadOnlyReplicaJpaTm;
|
||||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||||
|
@ -32,8 +32,8 @@ import javax.persistence.EntityManagerFactory;
|
||||||
modules = {
|
modules = {
|
||||||
ConfigModule.class,
|
ConfigModule.class,
|
||||||
CredentialModule.class,
|
CredentialModule.class,
|
||||||
KmsModule.class,
|
|
||||||
PersistenceModule.class,
|
PersistenceModule.class,
|
||||||
|
SecretManagerKeyringModule.class,
|
||||||
SecretManagerModule.class,
|
SecretManagerModule.class,
|
||||||
UtilsModule.class
|
UtilsModule.class
|
||||||
})
|
})
|
||||||
|
|
|
@ -29,12 +29,11 @@ import google.registry.dns.writer.dnsupdate.DnsUpdateWriterModule;
|
||||||
import google.registry.keyring.KeyringModule;
|
import google.registry.keyring.KeyringModule;
|
||||||
import google.registry.keyring.api.DummyKeyringModule;
|
import google.registry.keyring.api.DummyKeyringModule;
|
||||||
import google.registry.keyring.api.KeyModule;
|
import google.registry.keyring.api.KeyModule;
|
||||||
import google.registry.keyring.kms.KmsModule;
|
import google.registry.keyring.secretmanager.SecretManagerKeyringModule;
|
||||||
import google.registry.persistence.PersistenceModule;
|
import google.registry.persistence.PersistenceModule;
|
||||||
import google.registry.persistence.PersistenceModule.NomulusToolJpaTm;
|
import google.registry.persistence.PersistenceModule.NomulusToolJpaTm;
|
||||||
import google.registry.persistence.PersistenceModule.ReadOnlyReplicaJpaTm;
|
import google.registry.persistence.PersistenceModule.ReadOnlyReplicaJpaTm;
|
||||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||||
import google.registry.privileges.secretmanager.SecretManagerModule;
|
|
||||||
import google.registry.rde.RdeModule;
|
import google.registry.rde.RdeModule;
|
||||||
import google.registry.request.Modules.GsonModule;
|
import google.registry.request.Modules.GsonModule;
|
||||||
import google.registry.request.Modules.UrlConnectionServiceModule;
|
import google.registry.request.Modules.UrlConnectionServiceModule;
|
||||||
|
@ -70,13 +69,13 @@ import javax.inject.Singleton;
|
||||||
GsonModule.class,
|
GsonModule.class,
|
||||||
KeyModule.class,
|
KeyModule.class,
|
||||||
KeyringModule.class,
|
KeyringModule.class,
|
||||||
KmsModule.class,
|
SecretManagerKeyringModule.class,
|
||||||
LocalCredentialModule.class,
|
LocalCredentialModule.class,
|
||||||
PersistenceModule.class,
|
PersistenceModule.class,
|
||||||
RdeModule.class,
|
RdeModule.class,
|
||||||
RegistryToolDataflowModule.class,
|
RegistryToolDataflowModule.class,
|
||||||
RequestFactoryModule.class,
|
RequestFactoryModule.class,
|
||||||
SecretManagerModule.class,
|
google.registry.privileges.secretmanager.SecretManagerModule.class,
|
||||||
UrlConnectionServiceModule.class,
|
UrlConnectionServiceModule.class,
|
||||||
UrlFetchServiceModule.class,
|
UrlFetchServiceModule.class,
|
||||||
UserServiceModule.class,
|
UserServiceModule.class,
|
||||||
|
|
|
@ -20,7 +20,7 @@ import static google.registry.keyring.api.KeySerializer.deserializeString;
|
||||||
|
|
||||||
import com.beust.jcommander.Parameter;
|
import com.beust.jcommander.Parameter;
|
||||||
import com.beust.jcommander.Parameters;
|
import com.beust.jcommander.Parameters;
|
||||||
import google.registry.keyring.kms.KmsUpdater;
|
import google.registry.keyring.secretmanager.SecretManagerKeyringUpdater;
|
||||||
import google.registry.tools.params.KeyringKeyName;
|
import google.registry.tools.params.KeyringKeyName;
|
||||||
import google.registry.tools.params.PathParameter;
|
import google.registry.tools.params.PathParameter;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
@ -33,7 +33,7 @@ import javax.inject.Inject;
|
||||||
@Parameters(separators = " =", commandDescription = "Update values of secret in the keyring.")
|
@Parameters(separators = " =", commandDescription = "Update values of secret in the keyring.")
|
||||||
final class UpdateKeyringSecretCommand implements CommandWithRemoteApi {
|
final class UpdateKeyringSecretCommand implements CommandWithRemoteApi {
|
||||||
|
|
||||||
@Inject KmsUpdater kmsUpdater;
|
@Inject SecretManagerKeyringUpdater secretManagerKeyringUpdater;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
UpdateKeyringSecretCommand() {}
|
UpdateKeyringSecretCommand() {}
|
||||||
|
@ -55,35 +55,35 @@ final class UpdateKeyringSecretCommand implements CommandWithRemoteApi {
|
||||||
|
|
||||||
switch (keyringKeyName) {
|
switch (keyringKeyName) {
|
||||||
case BRDA_RECEIVER_PUBLIC_KEY:
|
case BRDA_RECEIVER_PUBLIC_KEY:
|
||||||
kmsUpdater.setBrdaReceiverPublicKey(deserializePublicKey(input));
|
secretManagerKeyringUpdater.setBrdaReceiverPublicKey(deserializePublicKey(input));
|
||||||
break;
|
break;
|
||||||
case BRDA_SIGNING_KEY_PAIR:
|
case BRDA_SIGNING_KEY_PAIR:
|
||||||
kmsUpdater.setBrdaSigningKey(deserializeKeyPair(input));
|
secretManagerKeyringUpdater.setBrdaSigningKey(deserializeKeyPair(input));
|
||||||
break;
|
break;
|
||||||
case BRDA_SIGNING_PUBLIC_KEY:
|
case BRDA_SIGNING_PUBLIC_KEY:
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't update BRDA_SIGNING_PUBLIC_KEY directly."
|
"Can't update BRDA_SIGNING_PUBLIC_KEY directly."
|
||||||
+ " Must update public and private keys together using BRDA_SIGNING_KEY_PAIR.");
|
+ " Must update public and private keys together using BRDA_SIGNING_KEY_PAIR.");
|
||||||
case ICANN_REPORTING_PASSWORD:
|
case ICANN_REPORTING_PASSWORD:
|
||||||
kmsUpdater.setIcannReportingPassword(deserializeString(input));
|
secretManagerKeyringUpdater.setIcannReportingPassword(deserializeString(input));
|
||||||
break;
|
break;
|
||||||
case JSON_CREDENTIAL:
|
case JSON_CREDENTIAL:
|
||||||
kmsUpdater.setJsonCredential(deserializeString(input));
|
secretManagerKeyringUpdater.setJsonCredential(deserializeString(input));
|
||||||
break;
|
break;
|
||||||
case MARKSDB_DNL_LOGIN_AND_PASSWORD:
|
case MARKSDB_DNL_LOGIN_AND_PASSWORD:
|
||||||
kmsUpdater.setMarksdbDnlLoginAndPassword(deserializeString(input));
|
secretManagerKeyringUpdater.setMarksdbDnlLoginAndPassword(deserializeString(input));
|
||||||
break;
|
break;
|
||||||
case MARKSDB_LORDN_PASSWORD:
|
case MARKSDB_LORDN_PASSWORD:
|
||||||
kmsUpdater.setMarksdbLordnPassword(deserializeString(input));
|
secretManagerKeyringUpdater.setMarksdbLordnPassword(deserializeString(input));
|
||||||
break;
|
break;
|
||||||
case MARKSDB_SMDRL_LOGIN_AND_PASSWORD:
|
case MARKSDB_SMDRL_LOGIN_AND_PASSWORD:
|
||||||
kmsUpdater.setMarksdbSmdrlLoginAndPassword(deserializeString(input));
|
secretManagerKeyringUpdater.setMarksdbSmdrlLoginAndPassword(deserializeString(input));
|
||||||
break;
|
break;
|
||||||
case RDE_RECEIVER_PUBLIC_KEY:
|
case RDE_RECEIVER_PUBLIC_KEY:
|
||||||
kmsUpdater.setRdeReceiverPublicKey(deserializePublicKey(input));
|
secretManagerKeyringUpdater.setRdeReceiverPublicKey(deserializePublicKey(input));
|
||||||
break;
|
break;
|
||||||
case RDE_SIGNING_KEY_PAIR:
|
case RDE_SIGNING_KEY_PAIR:
|
||||||
kmsUpdater.setRdeSigningKey(deserializeKeyPair(input));
|
secretManagerKeyringUpdater.setRdeSigningKey(deserializeKeyPair(input));
|
||||||
break;
|
break;
|
||||||
case RDE_SIGNING_PUBLIC_KEY:
|
case RDE_SIGNING_PUBLIC_KEY:
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
@ -95,16 +95,16 @@ final class UpdateKeyringSecretCommand implements CommandWithRemoteApi {
|
||||||
//
|
//
|
||||||
// Hence we can and need to update the private and public keys individually.
|
// Hence we can and need to update the private and public keys individually.
|
||||||
case RDE_SSH_CLIENT_PRIVATE_KEY:
|
case RDE_SSH_CLIENT_PRIVATE_KEY:
|
||||||
kmsUpdater.setRdeSshClientPrivateKey(deserializeString(input));
|
secretManagerKeyringUpdater.setRdeSshClientPrivateKey(deserializeString(input));
|
||||||
break;
|
break;
|
||||||
case RDE_SSH_CLIENT_PUBLIC_KEY:
|
case RDE_SSH_CLIENT_PUBLIC_KEY:
|
||||||
kmsUpdater.setRdeSshClientPublicKey(deserializeString(input));
|
secretManagerKeyringUpdater.setRdeSshClientPublicKey(deserializeString(input));
|
||||||
break;
|
break;
|
||||||
case RDE_STAGING_KEY_PAIR:
|
case RDE_STAGING_KEY_PAIR:
|
||||||
kmsUpdater.setRdeStagingKey(deserializeKeyPair(input));
|
secretManagerKeyringUpdater.setRdeStagingKey(deserializeKeyPair(input));
|
||||||
break;
|
break;
|
||||||
case SAFE_BROWSING_API_KEY:
|
case SAFE_BROWSING_API_KEY:
|
||||||
kmsUpdater.setSafeBrowsingAPIKey(deserializeString(input));
|
secretManagerKeyringUpdater.setSafeBrowsingAPIKey(deserializeString(input));
|
||||||
break;
|
break;
|
||||||
case RDE_STAGING_PUBLIC_KEY:
|
case RDE_STAGING_PUBLIC_KEY:
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
@ -112,7 +112,7 @@ final class UpdateKeyringSecretCommand implements CommandWithRemoteApi {
|
||||||
+ " Must update public and private keys together using RDE_STAGING_KEY_PAIR.");
|
+ " Must update public and private keys together using RDE_STAGING_KEY_PAIR.");
|
||||||
}
|
}
|
||||||
|
|
||||||
kmsUpdater.update();
|
secretManagerKeyringUpdater.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,171 +0,0 @@
|
||||||
// Copyright 2017 The Nomulus Authors. 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 google.registry.keyring.kms;
|
|
||||||
|
|
||||||
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
|
|
||||||
import com.google.api.client.http.GenericUrl;
|
|
||||||
import com.google.api.client.http.HttpContent;
|
|
||||||
import com.google.api.client.http.HttpRequest;
|
|
||||||
import com.google.api.client.http.HttpRequestFactory;
|
|
||||||
import com.google.api.client.http.HttpResponse;
|
|
||||||
import com.google.api.client.http.HttpTransport;
|
|
||||||
import com.google.api.client.http.LowLevelHttpRequest;
|
|
||||||
import com.google.api.client.http.LowLevelHttpResponse;
|
|
||||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
/** A helper to create instances of {@link GoogleJsonResponseException}. */
|
|
||||||
public class GoogleJsonResponseExceptionHelper {
|
|
||||||
/**
|
|
||||||
* @param statusCode the status code that should be in the returned {@link
|
|
||||||
* GoogleJsonResponseException}
|
|
||||||
* @return a {@link GoogleJsonResponseException} with the status code {@code statusCode}
|
|
||||||
* @throws IOException shouldn't occur
|
|
||||||
*/
|
|
||||||
public static GoogleJsonResponseException create(int statusCode) throws IOException {
|
|
||||||
HttpResponse response = createHttpResponse(statusCode, null);
|
|
||||||
return GoogleJsonResponseException.from(new JacksonFactory(), response);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HttpResponse createHttpResponse(int statusCode, InputStream content)
|
|
||||||
throws IOException {
|
|
||||||
FakeHttpTransport transport = new FakeHttpTransport(statusCode, content);
|
|
||||||
HttpRequestFactory factory = transport.createRequestFactory();
|
|
||||||
HttpRequest request =
|
|
||||||
factory.buildRequest(
|
|
||||||
"foo", new GenericUrl("http://example.com/bar"), new EmptyHttpContent());
|
|
||||||
request.setThrowExceptionOnExecuteError(false);
|
|
||||||
return request.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class FakeHttpTransport extends HttpTransport {
|
|
||||||
private final int statusCode;
|
|
||||||
private final InputStream content;
|
|
||||||
|
|
||||||
FakeHttpTransport(int statusCode, InputStream content) {
|
|
||||||
this.statusCode = statusCode;
|
|
||||||
this.content = content;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected LowLevelHttpRequest buildRequest(String method, String url) {
|
|
||||||
return new FakeLowLevelHttpRequest(statusCode, content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class FakeLowLevelHttpRequest extends LowLevelHttpRequest {
|
|
||||||
private final int statusCode;
|
|
||||||
private final InputStream content;
|
|
||||||
|
|
||||||
FakeLowLevelHttpRequest(int statusCode, InputStream content) {
|
|
||||||
this.statusCode = statusCode;
|
|
||||||
this.content = content;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addHeader(String name, String value) {
|
|
||||||
// Nothing!
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LowLevelHttpResponse execute() {
|
|
||||||
return new FakeLowLevelHttpResponse(statusCode, content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class FakeLowLevelHttpResponse extends LowLevelHttpResponse {
|
|
||||||
private final int statusCode;
|
|
||||||
private final InputStream content;
|
|
||||||
|
|
||||||
FakeLowLevelHttpResponse(int statusCode, InputStream content) {
|
|
||||||
this.statusCode = statusCode;
|
|
||||||
this.content = content;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream getContent() {
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getContentEncoding() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getContentLength() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getContentType() {
|
|
||||||
return "text/json";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getStatusLine() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getStatusCode() {
|
|
||||||
return statusCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getReasonPhrase() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getHeaderCount() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHeaderName(int index) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHeaderValue(int index) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class EmptyHttpContent implements HttpContent {
|
|
||||||
@Override
|
|
||||||
public long getLength() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return "text/json";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean retrySupported() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeTo(OutputStream out) {
|
|
||||||
// Nothing!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,226 +0,0 @@
|
||||||
// Copyright 2017 The Nomulus Authors. 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 google.registry.keyring.kms;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
|
||||||
import static org.mockito.Mockito.never;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
|
|
||||||
import com.google.api.client.http.HttpResponse;
|
|
||||||
import com.google.api.client.http.HttpResponseException;
|
|
||||||
import com.google.api.services.cloudkms.v1.CloudKMS;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.CryptoKey;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.CryptoKeyVersion;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.DecryptRequest;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.DecryptResponse;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.EncryptRequest;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.EncryptResponse;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.KeyRing;
|
|
||||||
import com.google.api.services.cloudkms.v1.model.UpdateCryptoKeyPrimaryVersionRequest;
|
|
||||||
import google.registry.testing.FakeClock;
|
|
||||||
import google.registry.testing.FakeSleeper;
|
|
||||||
import google.registry.util.Retrier;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
import org.mockito.Captor;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
|
||||||
import org.mockito.junit.jupiter.MockitoSettings;
|
|
||||||
import org.mockito.quality.Strictness;
|
|
||||||
|
|
||||||
/** Unit tests for {@link KmsConnectionImpl}. */
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
|
||||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
|
||||||
class KmsConnectionImplTest {
|
|
||||||
|
|
||||||
@Mock private CloudKMS kms;
|
|
||||||
@Mock private CloudKMS.Projects kmsProjects;
|
|
||||||
@Mock private CloudKMS.Projects.Locations kmsLocations;
|
|
||||||
@Mock private CloudKMS.Projects.Locations.KeyRings kmsKeyRings;
|
|
||||||
@Mock private CloudKMS.Projects.Locations.KeyRings.Get kmsKeyRingsGet;
|
|
||||||
@Mock private CloudKMS.Projects.Locations.KeyRings.Create kmsKeyRingsCreate;
|
|
||||||
@Mock private CloudKMS.Projects.Locations.KeyRings.CryptoKeys kmsCryptoKeys;
|
|
||||||
@Mock private CloudKMS.Projects.Locations.KeyRings.CryptoKeys.Get kmsCryptoKeysGet;
|
|
||||||
@Mock private CloudKMS.Projects.Locations.KeyRings.CryptoKeys.Create kmsCryptoKeysCreate;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private CloudKMS.Projects.Locations.KeyRings.CryptoKeys.UpdatePrimaryVersion updatePrimaryVersion;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private CloudKMS.Projects.Locations.KeyRings.CryptoKeys.CryptoKeyVersions kmsCryptoKeyVersions;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private CloudKMS.Projects.Locations.KeyRings.CryptoKeys.CryptoKeyVersions.Create
|
|
||||||
kmsCryptoKeyVersionsCreate;
|
|
||||||
|
|
||||||
@Mock private CloudKMS.Projects.Locations.KeyRings.CryptoKeys.Encrypt kmsCryptoKeysEncrypt;
|
|
||||||
@Mock private CloudKMS.Projects.Locations.KeyRings.CryptoKeys.Decrypt kmsCryptoKeysDecrypt;
|
|
||||||
|
|
||||||
@Captor private ArgumentCaptor<KeyRing> keyRing;
|
|
||||||
@Captor private ArgumentCaptor<CryptoKey> cryptoKey;
|
|
||||||
@Captor private ArgumentCaptor<CryptoKeyVersion> cryptoKeyVersion;
|
|
||||||
@Captor private ArgumentCaptor<String> locationName;
|
|
||||||
@Captor private ArgumentCaptor<String> keyRingName;
|
|
||||||
@Captor private ArgumentCaptor<String> cryptoKeyName;
|
|
||||||
@Captor private ArgumentCaptor<EncryptRequest> encryptRequest;
|
|
||||||
@Captor private ArgumentCaptor<DecryptRequest> decryptRequest;
|
|
||||||
|
|
||||||
@Captor
|
|
||||||
private ArgumentCaptor<UpdateCryptoKeyPrimaryVersionRequest> updateCryptoKeyPrimaryVersionRequest;
|
|
||||||
|
|
||||||
private final Retrier retrier = new Retrier(new FakeSleeper(new FakeClock()), 3);
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void beforeEach() throws Exception {
|
|
||||||
when(kms.projects()).thenReturn(kmsProjects);
|
|
||||||
when(kmsProjects.locations()).thenReturn(kmsLocations);
|
|
||||||
when(kmsLocations.keyRings()).thenReturn(kmsKeyRings);
|
|
||||||
when(kmsKeyRings.get(anyString())).thenReturn(kmsKeyRingsGet);
|
|
||||||
when(kmsKeyRings.create(anyString(), any(KeyRing.class))).thenReturn(kmsKeyRingsCreate);
|
|
||||||
when(kmsKeyRingsCreate.setKeyRingId(anyString())).thenReturn(kmsKeyRingsCreate);
|
|
||||||
when(kmsKeyRings.cryptoKeys()).thenReturn(kmsCryptoKeys);
|
|
||||||
when(kmsCryptoKeys.get(anyString())).thenReturn(kmsCryptoKeysGet);
|
|
||||||
when(kmsCryptoKeys.create(anyString(), any(CryptoKey.class))).thenReturn(kmsCryptoKeysCreate);
|
|
||||||
when(kmsCryptoKeysCreate.setCryptoKeyId(anyString())).thenReturn(kmsCryptoKeysCreate);
|
|
||||||
when(kmsCryptoKeys.cryptoKeyVersions()).thenReturn(kmsCryptoKeyVersions);
|
|
||||||
when(kmsCryptoKeyVersions.create(anyString(), any(CryptoKeyVersion.class)))
|
|
||||||
.thenReturn(kmsCryptoKeyVersionsCreate);
|
|
||||||
when(kmsCryptoKeyVersionsCreate.execute())
|
|
||||||
.thenReturn(new CryptoKeyVersion().setName(KmsTestHelper.DUMMY_CRYPTO_KEY_VERSION));
|
|
||||||
when(kmsCryptoKeys.encrypt(anyString(), any(EncryptRequest.class)))
|
|
||||||
.thenReturn(kmsCryptoKeysEncrypt);
|
|
||||||
when(kmsCryptoKeysEncrypt.execute())
|
|
||||||
.thenReturn(
|
|
||||||
new EncryptResponse()
|
|
||||||
.setName(KmsTestHelper.DUMMY_CRYPTO_KEY_VERSION)
|
|
||||||
.setCiphertext(KmsTestHelper.DUMMY_ENCRYPTED_VALUE));
|
|
||||||
when(kmsCryptoKeys.decrypt(anyString(), any(DecryptRequest.class)))
|
|
||||||
.thenReturn(kmsCryptoKeysDecrypt);
|
|
||||||
when(kmsCryptoKeys.updatePrimaryVersion(
|
|
||||||
anyString(), any(UpdateCryptoKeyPrimaryVersionRequest.class)))
|
|
||||||
.thenReturn(updatePrimaryVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test_encrypt_createsKeyRingIfNotFound() throws Exception {
|
|
||||||
when(kmsKeyRingsGet.execute()).thenThrow(createNotFoundException());
|
|
||||||
|
|
||||||
new KmsConnectionImpl("foo", "bar", retrier, kms).encrypt("key", "moo".getBytes(UTF_8));
|
|
||||||
|
|
||||||
verify(kmsKeyRings).create(locationName.capture(), keyRing.capture());
|
|
||||||
assertThat(locationName.getValue()).isEqualTo("projects/foo/locations/global");
|
|
||||||
assertThat(keyRing.getValue()).isEqualTo(new KeyRing());
|
|
||||||
verify(kmsKeyRingsCreate).setKeyRingId(keyRingName.capture());
|
|
||||||
assertThat(keyRingName.getValue()).isEqualTo("bar");
|
|
||||||
|
|
||||||
verify(kmsKeyRingsCreate).execute();
|
|
||||||
verifyEncryptKmsApiCalls(
|
|
||||||
"moo",
|
|
||||||
"projects/foo/locations/global/keyRings/bar",
|
|
||||||
"projects/foo/locations/global/keyRings/bar/cryptoKeys/key");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test_encrypt_newCryptoKey() throws Exception {
|
|
||||||
when(kmsCryptoKeysGet.execute()).thenThrow(createNotFoundException());
|
|
||||||
|
|
||||||
new KmsConnectionImpl("foo", "bar", retrier, kms).encrypt("key", "moo".getBytes(UTF_8));
|
|
||||||
|
|
||||||
verify(kmsCryptoKeys).create(keyRingName.capture(), cryptoKey.capture());
|
|
||||||
assertThat(keyRingName.getValue()).isEqualTo("projects/foo/locations/global/keyRings/bar");
|
|
||||||
assertThat(cryptoKey.getValue()).isEqualTo(new CryptoKey().setPurpose("ENCRYPT_DECRYPT"));
|
|
||||||
verify(kmsCryptoKeysCreate).setCryptoKeyId(cryptoKeyName.capture());
|
|
||||||
assertThat(cryptoKeyName.getValue()).isEqualTo("key");
|
|
||||||
verify(kmsCryptoKeysCreate).execute();
|
|
||||||
verify(kmsCryptoKeyVersionsCreate, never()).execute();
|
|
||||||
verify(updatePrimaryVersion, never()).execute();
|
|
||||||
|
|
||||||
verifyEncryptKmsApiCalls(
|
|
||||||
"moo",
|
|
||||||
"projects/foo/locations/global/keyRings/bar",
|
|
||||||
"projects/foo/locations/global/keyRings/bar/cryptoKeys/key");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test_encrypt() throws Exception {
|
|
||||||
new KmsConnectionImpl("foo", "bar", retrier, kms).encrypt("key", "moo".getBytes(UTF_8));
|
|
||||||
|
|
||||||
verify(kmsCryptoKeyVersions).create(cryptoKeyName.capture(), cryptoKeyVersion.capture());
|
|
||||||
assertThat(cryptoKeyName.getValue())
|
|
||||||
.isEqualTo("projects/foo/locations/global/keyRings/bar/cryptoKeys/key");
|
|
||||||
|
|
||||||
verify(kmsCryptoKeys)
|
|
||||||
.updatePrimaryVersion(
|
|
||||||
cryptoKeyName.capture(), updateCryptoKeyPrimaryVersionRequest.capture());
|
|
||||||
assertThat(cryptoKeyName.getValue())
|
|
||||||
.isEqualTo("projects/foo/locations/global/keyRings/bar/cryptoKeys/key");
|
|
||||||
assertThat(updateCryptoKeyPrimaryVersionRequest.getValue())
|
|
||||||
.isEqualTo(
|
|
||||||
new UpdateCryptoKeyPrimaryVersionRequest()
|
|
||||||
.setCryptoKeyVersionId(KmsTestHelper.DUMMY_CRYPTO_KEY_VERSION));
|
|
||||||
|
|
||||||
verifyEncryptKmsApiCalls(
|
|
||||||
"moo",
|
|
||||||
"projects/foo/locations/global/keyRings/bar",
|
|
||||||
"projects/foo/locations/global/keyRings/bar/cryptoKeys/key");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test_decrypt() throws Exception {
|
|
||||||
when(kmsCryptoKeysDecrypt.execute())
|
|
||||||
.thenReturn(new DecryptResponse().encodePlaintext("moo".getBytes(UTF_8)));
|
|
||||||
|
|
||||||
byte[] plaintext = new KmsConnectionImpl("foo", "bar", retrier, kms).decrypt("key", "blah");
|
|
||||||
|
|
||||||
verify(kmsCryptoKeys).decrypt(cryptoKeyName.capture(), decryptRequest.capture());
|
|
||||||
assertThat(cryptoKeyName.getValue())
|
|
||||||
.isEqualTo("projects/foo/locations/global/keyRings/bar/cryptoKeys/key");
|
|
||||||
assertThat(decryptRequest.getValue()).isEqualTo(new DecryptRequest().setCiphertext("blah"));
|
|
||||||
assertThat(plaintext).isEqualTo("moo".getBytes(UTF_8));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void verifyEncryptKmsApiCalls(
|
|
||||||
String goldenValue, String goldenCryptoKeyRingName, String goldenCryptoKeyName)
|
|
||||||
throws Exception {
|
|
||||||
verify(kmsKeyRings).get(keyRingName.capture());
|
|
||||||
assertThat(keyRingName.getValue()).isEqualTo(goldenCryptoKeyRingName);
|
|
||||||
|
|
||||||
verify(kmsCryptoKeys).get(cryptoKeyName.capture());
|
|
||||||
assertThat(cryptoKeyName.getValue()).isEqualTo(goldenCryptoKeyName);
|
|
||||||
|
|
||||||
verify(kmsCryptoKeys).encrypt(cryptoKeyName.capture(), encryptRequest.capture());
|
|
||||||
assertThat(cryptoKeyName.getValue()).isEqualTo(goldenCryptoKeyName);
|
|
||||||
assertThat(encryptRequest.getValue())
|
|
||||||
.isEqualTo(new EncryptRequest().encodePlaintext(goldenValue.getBytes(UTF_8)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GoogleJsonResponseException createNotFoundException() throws Exception {
|
|
||||||
ByteArrayInputStream inputStream = new ByteArrayInputStream("".getBytes(UTF_8));
|
|
||||||
HttpResponse response = GoogleJsonResponseExceptionHelper.createHttpResponse(404, inputStream);
|
|
||||||
HttpResponseException.Builder httpResponseExceptionBuilder =
|
|
||||||
new HttpResponseException.Builder(response);
|
|
||||||
httpResponseExceptionBuilder.setStatusCode(404);
|
|
||||||
httpResponseExceptionBuilder.setStatusMessage("NOT_FOUND");
|
|
||||||
return new GoogleJsonResponseException(httpResponseExceptionBuilder, null);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package google.registry.keyring.kms;
|
package google.registry.keyring.secretmanager;
|
||||||
|
|
||||||
import static com.google.common.io.Resources.getResource;
|
import static com.google.common.io.Resources.getResource;
|
||||||
|
|
||||||
|
@ -26,15 +26,16 @@ import org.bouncycastle.openpgp.bc.BcPGPSecretKeyRing;
|
||||||
import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
|
import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
|
||||||
import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
|
import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
|
||||||
|
|
||||||
/** Stores dummy values for test use in {@link KmsUpdaterTest}. */
|
/** Stores dummy values for test use in {@link SecretManagerKeyringUpdaterTest}. */
|
||||||
final class KmsTestHelper {
|
final class SecretManagerKeyringTestHelper {
|
||||||
|
|
||||||
static final String DUMMY_CRYPTO_KEY_VERSION = "cheeseburger";
|
static final String DUMMY_CRYPTO_KEY_VERSION = "cheeseburger";
|
||||||
static final String DUMMY_ENCRYPTED_VALUE = "meow";
|
static final String DUMMY_ENCRYPTED_VALUE = "meow";
|
||||||
|
|
||||||
/** The contents of a dummy PGP private key stored in a file. */
|
/** The contents of a dummy PGP private key stored in a file. */
|
||||||
private static final ByteSource PGP_PRIVATE_KEYRING =
|
private static final ByteSource PGP_PRIVATE_KEYRING =
|
||||||
Resources.asByteSource(getResource(KmsTestHelper.class, "pgp-private-keyring-registry.asc"));
|
Resources.asByteSource(
|
||||||
|
getResource(SecretManagerKeyringTestHelper.class, "pgp-private-keyring-registry.asc"));
|
||||||
|
|
||||||
private static BcPGPSecretKeyRing getPrivateKeyring() throws Exception {
|
private static BcPGPSecretKeyRing getPrivateKeyring() throws Exception {
|
||||||
return new BcPGPSecretKeyRing(PGPUtil.getDecoderStream(PGP_PRIVATE_KEYRING.openStream()));
|
return new BcPGPSecretKeyRing(PGPUtil.getDecoderStream(PGP_PRIVATE_KEYRING.openStream()));
|
||||||
|
@ -53,5 +54,5 @@ final class KmsTestHelper {
|
||||||
.build(new char[0])));
|
.build(new char[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
private KmsTestHelper() {}
|
private SecretManagerKeyringTestHelper() {}
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package google.registry.keyring.kms;
|
package google.registry.keyring.secretmanager;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
@ -28,22 +28,21 @@ import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
/** Unit tests for {@link KmsKeyring} and {@link KmsUpdater} */
|
/** Unit tests for {@link SecretManagerKeyring} and {@link SecretManagerKeyringUpdater} */
|
||||||
// TODO(2021-07-01): Rename this class along with KmsKeyring
|
public class SecretManagerKeyringUpdaterTest {
|
||||||
public class KmsUpdaterTest {
|
|
||||||
|
|
||||||
@RegisterExtension
|
@RegisterExtension
|
||||||
public final BouncyCastleProviderExtension bouncy = new BouncyCastleProviderExtension();
|
public final BouncyCastleProviderExtension bouncy = new BouncyCastleProviderExtension();
|
||||||
|
|
||||||
private KeyringSecretStore secretStore;
|
private KeyringSecretStore secretStore;
|
||||||
private KmsUpdater updater;
|
private SecretManagerKeyringUpdater updater;
|
||||||
private KmsKeyring keyring;
|
private SecretManagerKeyring keyring;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void beforeEach() {
|
void beforeEach() {
|
||||||
secretStore = new KeyringSecretStore(new FakeSecretManagerClient());
|
secretStore = new KeyringSecretStore(new FakeSecretManagerClient());
|
||||||
updater = new KmsUpdater(secretStore);
|
updater = new SecretManagerKeyringUpdater(secretStore);
|
||||||
keyring = new KmsKeyring(secretStore);
|
keyring = new SecretManagerKeyring(secretStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -66,7 +65,7 @@ public class KmsUpdaterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void brdaReceiverKey() throws Exception {
|
void brdaReceiverKey() throws Exception {
|
||||||
PGPPublicKey publicKey = KmsTestHelper.getPublicKey();
|
PGPPublicKey publicKey = SecretManagerKeyringTestHelper.getPublicKey();
|
||||||
updater.setBrdaReceiverPublicKey(publicKey).update();
|
updater.setBrdaReceiverPublicKey(publicKey).update();
|
||||||
|
|
||||||
assertThat(keyring.getBrdaReceiverKey().getFingerprint()).isEqualTo(publicKey.getFingerprint());
|
assertThat(keyring.getBrdaReceiverKey().getFingerprint()).isEqualTo(publicKey.getFingerprint());
|
||||||
|
@ -75,12 +74,14 @@ public class KmsUpdaterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void brdaSigningKey() throws Exception {
|
void brdaSigningKey() throws Exception {
|
||||||
PGPKeyPair keyPair = KmsTestHelper.getKeyPair();
|
PGPKeyPair keyPair = SecretManagerKeyringTestHelper.getKeyPair();
|
||||||
updater.setBrdaSigningKey(keyPair).update();
|
updater.setBrdaSigningKey(keyPair).update();
|
||||||
|
|
||||||
assertThat(serializeKeyPair(keyring.getBrdaSigningKey())).isEqualTo(serializeKeyPair(keyPair));
|
assertThat(serializeKeyPair(keyring.getBrdaSigningKey())).isEqualTo(serializeKeyPair(keyPair));
|
||||||
verifyPersistedSecret("brda-signing-private", serializeKeyPair(KmsTestHelper.getKeyPair()));
|
verifyPersistedSecret(
|
||||||
verifyPersistedSecret("brda-signing-public", serializePublicKey(KmsTestHelper.getPublicKey()));
|
"brda-signing-private", serializeKeyPair(SecretManagerKeyringTestHelper.getKeyPair()));
|
||||||
|
verifyPersistedSecret(
|
||||||
|
"brda-signing-public", serializePublicKey(SecretManagerKeyringTestHelper.getPublicKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -130,16 +131,17 @@ public class KmsUpdaterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void rdeReceiverKey() throws Exception {
|
void rdeReceiverKey() throws Exception {
|
||||||
PGPPublicKey publicKey = KmsTestHelper.getPublicKey();
|
PGPPublicKey publicKey = SecretManagerKeyringTestHelper.getPublicKey();
|
||||||
updater.setRdeReceiverPublicKey(publicKey).update();
|
updater.setRdeReceiverPublicKey(publicKey).update();
|
||||||
|
|
||||||
assertThat(keyring.getRdeReceiverKey().getFingerprint()).isEqualTo(publicKey.getFingerprint());
|
assertThat(keyring.getRdeReceiverKey().getFingerprint()).isEqualTo(publicKey.getFingerprint());
|
||||||
verifyPersistedSecret("rde-receiver-public", serializePublicKey(KmsTestHelper.getPublicKey()));
|
verifyPersistedSecret(
|
||||||
|
"rde-receiver-public", serializePublicKey(SecretManagerKeyringTestHelper.getPublicKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void rdeSigningKey() throws Exception {
|
void rdeSigningKey() throws Exception {
|
||||||
PGPKeyPair keyPair = KmsTestHelper.getKeyPair();
|
PGPKeyPair keyPair = SecretManagerKeyringTestHelper.getKeyPair();
|
||||||
updater.setRdeSigningKey(keyPair).update();
|
updater.setRdeSigningKey(keyPair).update();
|
||||||
|
|
||||||
assertThat(serializeKeyPair(keyring.getRdeSigningKey())).isEqualTo(serializeKeyPair(keyPair));
|
assertThat(serializeKeyPair(keyring.getRdeSigningKey())).isEqualTo(serializeKeyPair(keyPair));
|
||||||
|
@ -168,7 +170,7 @@ public class KmsUpdaterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void rdeStagingKey() throws Exception {
|
void rdeStagingKey() throws Exception {
|
||||||
PGPKeyPair keyPair = KmsTestHelper.getKeyPair();
|
PGPKeyPair keyPair = SecretManagerKeyringTestHelper.getKeyPair();
|
||||||
updater.setRdeStagingKey(keyPair).update();
|
updater.setRdeStagingKey(keyPair).update();
|
||||||
|
|
||||||
assertThat(serializePublicKey(keyring.getRdeStagingEncryptionKey()))
|
assertThat(serializePublicKey(keyring.getRdeStagingEncryptionKey()))
|
||||||
|
@ -181,7 +183,8 @@ public class KmsUpdaterTest {
|
||||||
keyring.getRdeStagingEncryptionKey(), keyring.getRdeStagingDecryptionKey())))
|
keyring.getRdeStagingEncryptionKey(), keyring.getRdeStagingDecryptionKey())))
|
||||||
.isEqualTo(serializeKeyPair(keyPair));
|
.isEqualTo(serializeKeyPair(keyPair));
|
||||||
verifyPersistedSecret("rde-staging-private", serializeKeyPair(keyPair));
|
verifyPersistedSecret("rde-staging-private", serializeKeyPair(keyPair));
|
||||||
verifyPersistedSecret("rde-staging-public", serializePublicKey(KmsTestHelper.getPublicKey()));
|
verifyPersistedSecret(
|
||||||
|
"rde-staging-public", serializePublicKey(SecretManagerKeyringTestHelper.getPublicKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyPersistedSecret(String secretName, String expectedPlainTextValue) {
|
private void verifyPersistedSecret(String secretName, String expectedPlainTextValue) {
|
|
@ -21,7 +21,7 @@ import dagger.Component;
|
||||||
import google.registry.config.CredentialModule;
|
import google.registry.config.CredentialModule;
|
||||||
import google.registry.config.RegistryConfig.Config;
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.config.RegistryConfig.ConfigModule;
|
import google.registry.config.RegistryConfig.ConfigModule;
|
||||||
import google.registry.keyring.kms.KmsModule;
|
import google.registry.keyring.secretmanager.SecretManagerKeyringModule;
|
||||||
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
|
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
|
||||||
import google.registry.privileges.secretmanager.SecretManagerModule;
|
import google.registry.privileges.secretmanager.SecretManagerModule;
|
||||||
import google.registry.testing.DatastoreEntityExtension;
|
import google.registry.testing.DatastoreEntityExtension;
|
||||||
|
@ -89,8 +89,8 @@ class PersistenceModuleTest {
|
||||||
modules = {
|
modules = {
|
||||||
ConfigModule.class,
|
ConfigModule.class,
|
||||||
CredentialModule.class,
|
CredentialModule.class,
|
||||||
KmsModule.class,
|
|
||||||
PersistenceModule.class,
|
PersistenceModule.class,
|
||||||
|
SecretManagerKeyringModule.class,
|
||||||
SecretManagerModule.class,
|
SecretManagerModule.class,
|
||||||
UtilsModule.class
|
UtilsModule.class
|
||||||
})
|
})
|
||||||
|
|
|
@ -164,18 +164,16 @@ allows the codebase to compile and run, but of course any actions that attempt
|
||||||
to connect to external services will fail because none of the keys are real.
|
to connect to external services will fail because none of the keys are real.
|
||||||
|
|
||||||
To configure a production registry system, you will need to either use the
|
To configure a production registry system, you will need to either use the
|
||||||
KmsKeyring or write your own replacement module using `DummyKeyringModule` for
|
SecretManagerKeyring or write your own replacement module using
|
||||||
guidance. Such a module should provide either an instance of
|
`DummyKeyringModule` for guidance. Such a module should provide either an
|
||||||
`InMemoryKeyring` or your own custom implementation of `Keyring`.
|
instance of `InMemoryKeyring` or your own custom implementation of `Keyring`.
|
||||||
|
|
||||||
In either case, configure the `keyring` section of the config file with the
|
In either case, configure the `keyring` section of the config file with the
|
||||||
appropriate parameters. Use an `activeKeyring` of "KMS" with a project id for
|
appropriate parameters. Use an `activeKeyring` of "CSM" with a project id for
|
||||||
KMS to configure accordingly, for example:
|
SecretManager to configure accordingly, for example:
|
||||||
|
|
||||||
keyring:
|
keyring:
|
||||||
activeKeyring: KMS
|
activeKeyring: CSM
|
||||||
kms:
|
|
||||||
projectId: acme-registry-keys
|
|
||||||
|
|
||||||
## Per-TLD configuration
|
## Per-TLD configuration
|
||||||
|
|
||||||
|
@ -316,35 +314,13 @@ connect to your database with gcloud:
|
||||||
From this, you should have a postgres prompt and be able to enter the "GRANT"
|
From this, you should have a postgres prompt and be able to enter the "GRANT"
|
||||||
command specified above.
|
command specified above.
|
||||||
|
|
||||||
### Cloud KMS
|
### Cloud SecretManager
|
||||||
|
|
||||||
You'll need to choose a project to host the KMS keyring. Best practice is to
|
You'll need to enable the SecretManager API in your project.
|
||||||
create a separate project with a strict IAM policy. However, you can use your
|
|
||||||
current project when experimenting.
|
|
||||||
|
|
||||||
You need to create a KMS keyring in the chosen project. The default keyring
|
|
||||||
name is 'nomulus', though you can override it in the config file.
|
|
||||||
|
|
||||||
$ gcloud kms keyrings create "nomulus" --location "global" \
|
|
||||||
--project $KEYS_PROJECT_ID
|
|
||||||
|
|
||||||
Next, you need to create two keys in the keyring:
|
|
||||||
|
|
||||||
$ gcloud kms keys create "cloud-sql-password-string" \
|
|
||||||
--project $KEYS_PROJECT_ID \
|
|
||||||
--location "global" \
|
|
||||||
--keyring "nomulus" \
|
|
||||||
--purpose "encryption"
|
|
||||||
|
|
||||||
$ gcloud kms keys create "tools-cloud-sql-password-string" \
|
|
||||||
--project $KEYS_PROJECT_ID \
|
|
||||||
--location "global" \
|
|
||||||
--keyring "nomulus" \
|
|
||||||
--purpose "encryption"
|
|
||||||
|
|
||||||
#### Install Cloud SQL Passwords in Nomulus Server
|
#### Install Cloud SQL Passwords in Nomulus Server
|
||||||
|
|
||||||
Use the update_kms_keyring command to upload the Cloud SQL passwords to the
|
Use the update_keyring_secret command to upload the Cloud SQL passwords to the
|
||||||
Nomulus server. We'll use the password same set of passwords we specified
|
Nomulus server. We'll use the password same set of passwords we specified
|
||||||
above when creating database user accounts. These should currently be stored
|
above when creating database user accounts. These should currently be stored
|
||||||
in `/tmp/server.pass`.
|
in `/tmp/server.pass`.
|
||||||
|
@ -353,12 +329,12 @@ Paste the password for the Registry server user to a file, say
|
||||||
/tmp/server.pass. Make sure to avoid any trailing '\n' inserted by the editor.
|
/tmp/server.pass. Make sure to avoid any trailing '\n' inserted by the editor.
|
||||||
|
|
||||||
$ set ENV=alpha
|
$ set ENV=alpha
|
||||||
$ nomulus -e $ENV update_kms_keyring --keyname CLOUD_SQL_PASSWORD \
|
$ nomulus -e $ENV update_keyring_secret --keyname CLOUD_SQL_PASSWORD \
|
||||||
--input /tmp/server.pass
|
--input /tmp/server.pass
|
||||||
|
|
||||||
Repeat the steps for the tools sql password:
|
Repeat the steps for the tools sql password:
|
||||||
|
|
||||||
$ nomulus -e $ENV update_kms_keyring --keyname TOOLS_CLOUD_SQL_PASSWORD \
|
$ nomulus -e $ENV update_keyring_secret --keyname TOOLS_CLOUD_SQL_PASSWORD \
|
||||||
--input /tmp/tools.pass
|
--input /tmp/tools.pass
|
||||||
|
|
||||||
Use get_keyring_secret command to verify the data you put in:
|
Use get_keyring_secret command to verify the data you put in:
|
||||||
|
@ -376,9 +352,7 @@ Use get_keyring_secret command to verify the data you put in:
|
||||||
instanceConnectionName: THE_NAME_SHOWN_ON_THE_DB_INFO_PAGE
|
instanceConnectionName: THE_NAME_SHOWN_ON_THE_DB_INFO_PAGE
|
||||||
|
|
||||||
keyring:
|
keyring:
|
||||||
activeKeyring: KMS
|
activeKeyring: CSM
|
||||||
kms:
|
|
||||||
projectId: KEYS_PROJECT_ID
|
|
||||||
|
|
||||||
registryTool:
|
registryTool:
|
||||||
clientId: TOOLS_OAUTH_CLIENT_ID
|
clientId: TOOLS_OAUTH_CLIENT_ID
|
||||||
|
|
|
@ -76,7 +76,6 @@ com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0=d
|
||||||
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-cloudkms:v1-rev20220701-1.32.1=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
|
||||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||||
|
|
|
@ -73,7 +73,6 @@ com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0=c
|
||||||
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-cloudkms:v1-rev20220701-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
|
||||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
|
|
|
@ -73,7 +73,6 @@ com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0=c
|
||||||
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-cloudkms:v1-rev20220701-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
|
||||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
|
|
|
@ -73,7 +73,6 @@ com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0=c
|
||||||
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-cloudkms:v1-rev20220701-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
|
||||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
|
|
|
@ -73,7 +73,6 @@ com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0=c
|
||||||
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-cloudkms:v1-rev20220701-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
|
||||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,default,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||||
|
|
Loading…
Add table
Reference in a new issue