From 242864d1981019cd0ed80d0682b5b015be71beef Mon Sep 17 00:00:00 2001 From: Weimin Yu Date: Fri, 4 Nov 2022 11:17:15 -0400 Subject: [PATCH] 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. --- core/build.gradle | 1 - core/gradle.lockfile | 1 - .../registry/config/RegistryConfig.java | 18 -- .../config/RegistryConfigSettings.java | 1 + .../registry/config/files/default-config.yaml | 3 +- .../registry/keyring/kms/EncryptResponse.java | 41 ---- .../registry/keyring/kms/KmsConnection.java | 48 ---- .../keyring/kms/KmsConnectionImpl.java | 177 -------------- .../registry/keyring/kms/KmsModule.java | 84 ------- .../SecretManagerKeyring.java} | 7 +- .../SecretManagerKeyringModule.java | 40 ++++ .../SecretManagerKeyringUpdater.java} | 88 +++---- .../module/backend/BackendComponent.java | 4 +- .../module/frontend/FrontendComponent.java | 4 +- .../module/pubapi/PubApiComponent.java | 4 +- .../registry/module/tools/ToolsComponent.java | 4 +- .../persistence/PersistenceComponent.java | 4 +- .../registry/tools/RegistryToolComponent.java | 7 +- .../tools/UpdateKeyringSecretCommand.java | 32 +-- .../GoogleJsonResponseExceptionHelper.java | 171 ------------- .../keyring/kms/KmsConnectionImplTest.java | 226 ------------------ .../SecretManagerKeyringTestHelper.java} | 11 +- .../SecretManagerKeyringUpdaterTest.java} | 37 +-- .../persistence/PersistenceModuleTest.java | 4 +- .../pgp-private-keyring-registry.asc | 0 .../pgp-public-keyring.asc | 0 docs/configuration.md | 50 +--- docs/gradle.lockfile | 1 - services/backend/gradle.lockfile | 1 - services/default/gradle.lockfile | 1 - services/pubapi/gradle.lockfile | 1 - services/tools/gradle.lockfile | 1 - 32 files changed, 161 insertions(+), 911 deletions(-) delete mode 100644 core/src/main/java/google/registry/keyring/kms/EncryptResponse.java delete mode 100644 core/src/main/java/google/registry/keyring/kms/KmsConnection.java delete mode 100644 core/src/main/java/google/registry/keyring/kms/KmsConnectionImpl.java delete mode 100644 core/src/main/java/google/registry/keyring/kms/KmsModule.java rename core/src/main/java/google/registry/keyring/{kms/KmsKeyring.java => secretmanager/SecretManagerKeyring.java} (96%) create mode 100644 core/src/main/java/google/registry/keyring/secretmanager/SecretManagerKeyringModule.java rename core/src/main/java/google/registry/keyring/{kms/KmsUpdater.java => secretmanager/SecretManagerKeyringUpdater.java} (53%) delete mode 100644 core/src/test/java/google/registry/keyring/kms/GoogleJsonResponseExceptionHelper.java delete mode 100644 core/src/test/java/google/registry/keyring/kms/KmsConnectionImplTest.java rename core/src/test/java/google/registry/keyring/{kms/KmsTestHelper.java => secretmanager/SecretManagerKeyringTestHelper.java} (85%) rename core/src/test/java/google/registry/keyring/{kms/KmsUpdaterTest.java => secretmanager/SecretManagerKeyringUpdaterTest.java} (84%) rename core/src/test/resources/google/registry/keyring/{kms => secretmanager}/pgp-private-keyring-registry.asc (100%) rename core/src/test/resources/google/registry/keyring/{kms => secretmanager}/pgp-public-keyring.asc (100%) diff --git a/core/build.gradle b/core/build.gradle index 044853bef..6f186272c 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -186,7 +186,6 @@ dependencies { 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-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-dns'] implementation deps['com.google.apis:google-api-services-drive'] diff --git a/core/gradle.lockfile b/core/gradle.lockfile index d8210754e..cc0d54693 100644 --- a/core/gradle.lockfile +++ b/core/gradle.lockfile @@ -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-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-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-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 diff --git a/core/src/main/java/google/registry/config/RegistryConfig.java b/core/src/main/java/google/registry/config/RegistryConfig.java index cd162f0b7..faca77ebf 100644 --- a/core/src/main/java/google/registry/config/RegistryConfig.java +++ b/core/src/main/java/google/registry/config/RegistryConfig.java @@ -1076,24 +1076,6 @@ public final class RegistryConfig { return config.keyring.activeKeyring; } - /** - * The name to use for the Cloud KMS KeyRing containing encryption keys for Nomulus secrets. - * - * @see projects.locations.keyRings - */ - @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 @Config("customLogicFactoryClass") public static String provideCustomLogicFactoryClass(RegistryConfigSettings config) { diff --git a/core/src/main/java/google/registry/config/RegistryConfigSettings.java b/core/src/main/java/google/registry/config/RegistryConfigSettings.java index 94e77240b..37901912d 100644 --- a/core/src/main/java/google/registry/config/RegistryConfigSettings.java +++ b/core/src/main/java/google/registry/config/RegistryConfigSettings.java @@ -214,6 +214,7 @@ public class RegistryConfigSettings { /** Configuration for keyrings (used to store secrets outside of source). */ public static class Keyring { public String activeKeyring; + // TODO(b/257276342): Remove after config files in nomulus-internal are updated. public Kms kms; } diff --git a/core/src/main/java/google/registry/config/files/default-config.yaml b/core/src/main/java/google/registry/config/files/default-config.yaml index 7e81620f3..96a61545b 100644 --- a/core/src/main/java/google/registry/config/files/default-config.yaml +++ b/core/src/main/java/google/registry/config/files/default-config.yaml @@ -449,7 +449,8 @@ beam: stagingBucketUrl: gcs-bucket-with-staged-templates 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 # Configuration options specific to Google Cloud KMS. diff --git a/core/src/main/java/google/registry/keyring/kms/EncryptResponse.java b/core/src/main/java/google/registry/keyring/kms/EncryptResponse.java deleted file mode 100644 index a4dee2718..000000000 --- a/core/src/main/java/google/registry/keyring/kms/EncryptResponse.java +++ /dev/null @@ -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(); -} diff --git a/core/src/main/java/google/registry/keyring/kms/KmsConnection.java b/core/src/main/java/google/registry/keyring/kms/KmsConnection.java deleted file mode 100644 index 5d4486746..000000000 --- a/core/src/main/java/google/registry/keyring/kms/KmsConnection.java +++ /dev/null @@ -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 projects.locations.keyRings.cryptoKeys.encrypt - */ - int MAX_SECRET_SIZE_BYTES = 64 * 1024; - - /** - * Encrypts a plaintext with CryptoKey {@code cryptoKeyName} on KeyRing {@code keyRingName}. - * - *

The latest CryptoKeyVersion is used to encrypt the value. The value must not be larger than - * {@code MAX_SECRET_SIZE_BYTES}. - * - *

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); -} diff --git a/core/src/main/java/google/registry/keyring/kms/KmsConnectionImpl.java b/core/src/main/java/google/registry/keyring/kms/KmsConnectionImpl.java deleted file mode 100644 index 483aaf099..000000000 --- a/core/src/main/java/google/registry/keyring/kms/KmsConnectionImpl.java +++ /dev/null @@ -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); - } -} diff --git a/core/src/main/java/google/registry/keyring/kms/KmsModule.java b/core/src/main/java/google/registry/keyring/kms/KmsModule.java deleted file mode 100644 index b517ae65e..000000000 --- a/core/src/main/java/google/registry/keyring/kms/KmsModule.java +++ /dev/null @@ -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); -} diff --git a/core/src/main/java/google/registry/keyring/kms/KmsKeyring.java b/core/src/main/java/google/registry/keyring/secretmanager/SecretManagerKeyring.java similarity index 96% rename from core/src/main/java/google/registry/keyring/kms/KmsKeyring.java rename to core/src/main/java/google/registry/keyring/secretmanager/SecretManagerKeyring.java index 0232a191c..56b2c217f 100644 --- a/core/src/main/java/google/registry/keyring/kms/KmsKeyring.java +++ b/core/src/main/java/google/registry/keyring/secretmanager/SecretManagerKeyring.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // 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.UPPER_UNDERSCORE; @@ -29,8 +29,7 @@ import org.bouncycastle.openpgp.PGPPrivateKey; import org.bouncycastle.openpgp.PGPPublicKey; /** 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 KmsKeyring implements Keyring { +public class SecretManagerKeyring implements Keyring { /** Key labels for private key secrets. */ enum PrivateKeyLabel { @@ -75,7 +74,7 @@ public class KmsKeyring implements Keyring { private final KeyringSecretStore secretStore; @Inject - KmsKeyring(KeyringSecretStore secretStore) { + SecretManagerKeyring(KeyringSecretStore secretStore) { this.secretStore = secretStore; } diff --git a/core/src/main/java/google/registry/keyring/secretmanager/SecretManagerKeyringModule.java b/core/src/main/java/google/registry/keyring/secretmanager/SecretManagerKeyringModule.java new file mode 100644 index 000000000..5234b9f95 --- /dev/null +++ b/core/src/main/java/google/registry/keyring/secretmanager/SecretManagerKeyringModule.java @@ -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); +} diff --git a/core/src/main/java/google/registry/keyring/kms/KmsUpdater.java b/core/src/main/java/google/registry/keyring/secretmanager/SecretManagerKeyringUpdater.java similarity index 53% rename from core/src/main/java/google/registry/keyring/kms/KmsUpdater.java rename to core/src/main/java/google/registry/keyring/secretmanager/SecretManagerKeyringUpdater.java index fcc3411a0..4e6c8d658 100644 --- a/core/src/main/java/google/registry/keyring/kms/KmsUpdater.java +++ b/core/src/main/java/google/registry/keyring/secretmanager/SecretManagerKeyringUpdater.java @@ -12,33 +12,33 @@ // See the License for the specific language governing permissions and // 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.checkState; -import static google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel.BRDA_SIGNING_PRIVATE; -import static google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel.RDE_SIGNING_PRIVATE; -import static google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel.RDE_STAGING_PRIVATE; -import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.BRDA_RECEIVER_PUBLIC; -import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.BRDA_SIGNING_PUBLIC; -import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_RECEIVER_PUBLIC; -import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_SIGNING_PUBLIC; -import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_STAGING_PUBLIC; -import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.ICANN_REPORTING_PASSWORD_STRING; -import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.JSON_CREDENTIAL_STRING; -import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.MARKSDB_DNL_LOGIN_STRING; -import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.MARKSDB_LORDN_PASSWORD_STRING; -import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.MARKSDB_SMDRL_LOGIN_STRING; -import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.RDE_SSH_CLIENT_PRIVATE_STRING; -import static google.registry.keyring.kms.KmsKeyring.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.PrivateKeyLabel.BRDA_SIGNING_PRIVATE; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.PrivateKeyLabel.RDE_SIGNING_PRIVATE; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.PrivateKeyLabel.RDE_STAGING_PRIVATE; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.BRDA_RECEIVER_PUBLIC; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.BRDA_SIGNING_PUBLIC; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.RDE_RECEIVER_PUBLIC; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.RDE_SIGNING_PUBLIC; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.RDE_STAGING_PUBLIC; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.ICANN_REPORTING_PASSWORD_STRING; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.JSON_CREDENTIAL_STRING; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.MARKSDB_DNL_LOGIN_STRING; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.MARKSDB_LORDN_PASSWORD_STRING; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.MARKSDB_SMDRL_LOGIN_STRING; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.RDE_SSH_CLIENT_PRIVATE_STRING; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.RDE_SSH_CLIENT_PUBLIC_STRING; +import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.SAFE_BROWSING_API_KEY; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import com.google.common.flogger.FluentLogger; import google.registry.keyring.api.KeySerializer; -import google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel; -import google.registry.keyring.kms.KmsKeyring.PublicKeyLabel; -import google.registry.keyring.kms.KmsKeyring.StringKeyLabel; +import google.registry.keyring.secretmanager.SecretManagerKeyring.PrivateKeyLabel; +import google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel; +import google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel; import google.registry.privileges.secretmanager.KeyringSecretStore; import java.io.IOException; import java.util.HashMap; @@ -50,73 +50,77 @@ import org.bouncycastle.openpgp.PGPKeyPair; import org.bouncycastle.openpgp.PGPPublicKey; /** - * The {@link KmsUpdater} accumulates updates to a {@link KmsKeyring} and persists them to KMS and - * Datastore when closed. + * The {@link SecretManagerKeyringUpdater} accumulates updates to a {@link SecretManagerKeyring} and + * persists them to KMS and Datastore when closed. */ -// TODO(2021-06-01): rename this class to SecretManagerKeyringUpdater -public final class KmsUpdater { +public final class SecretManagerKeyringUpdater { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); private final KeyringSecretStore secretStore; private final HashMap secretValues; @Inject - public KmsUpdater(KeyringSecretStore secretStore) { + public SecretManagerKeyringUpdater(KeyringSecretStore secretStore) { this.secretStore = secretStore; // Use LinkedHashMap to preserve insertion order on update() to simplify testing and debugging 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); } - 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); } - public KmsUpdater setRdeReceiverPublicKey(PGPPublicKey publicKey) throws IOException { + public SecretManagerKeyringUpdater setRdeReceiverPublicKey(PGPPublicKey publicKey) + throws IOException { 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); } - public KmsUpdater setBrdaReceiverPublicKey(PGPPublicKey publicKey) throws IOException { + public SecretManagerKeyringUpdater setBrdaReceiverPublicKey(PGPPublicKey publicKey) + throws IOException { return setPublicKey(publicKey, BRDA_RECEIVER_PUBLIC); } - public KmsUpdater setRdeSshClientPublicKey(String asciiPublicKey) { + public SecretManagerKeyringUpdater setRdeSshClientPublicKey(String asciiPublicKey) { 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); } - public KmsUpdater setSafeBrowsingAPIKey(String apiKey) { + public SecretManagerKeyringUpdater setSafeBrowsingAPIKey(String apiKey) { return setString(apiKey, SAFE_BROWSING_API_KEY); } - public KmsUpdater setIcannReportingPassword(String password) { + public SecretManagerKeyringUpdater setIcannReportingPassword(String password) { return setString(password, ICANN_REPORTING_PASSWORD_STRING); } - public KmsUpdater setMarksdbDnlLoginAndPassword(String login) { + public SecretManagerKeyringUpdater setMarksdbDnlLoginAndPassword(String login) { return setString(login, MARKSDB_DNL_LOGIN_STRING); } - public KmsUpdater setMarksdbLordnPassword(String password) { + public SecretManagerKeyringUpdater setMarksdbLordnPassword(String password) { return setString(password, MARKSDB_LORDN_PASSWORD_STRING); } - public KmsUpdater setMarksdbSmdrlLoginAndPassword(String login) { + public SecretManagerKeyringUpdater setMarksdbSmdrlLoginAndPassword(String login) { return setString(login, MARKSDB_SMDRL_LOGIN_STRING); } - public KmsUpdater setJsonCredential(String credential) { + public SecretManagerKeyringUpdater setJsonCredential(String credential) { 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); setSecret(stringKeyLabel.getLabel(), KeySerializer.serializeString(key)); return this; } - private KmsUpdater setPublicKey(PGPPublicKey publicKey, PublicKeyLabel publicKeyLabel) - throws IOException { + private SecretManagerKeyringUpdater setPublicKey( + PGPPublicKey publicKey, PublicKeyLabel publicKeyLabel) throws IOException { checkArgumentNotNull(publicKey); setSecret(publicKeyLabel.getLabel(), KeySerializer.serializePublicKey(publicKey)); return this; } - private KmsUpdater setKeyPair( + private SecretManagerKeyringUpdater setKeyPair( PGPKeyPair keyPair, PrivateKeyLabel privateKeyLabel, PublicKeyLabel publicKeyLabel) throws IOException, PGPException { checkArgumentNotNull(keyPair); diff --git a/core/src/main/java/google/registry/module/backend/BackendComponent.java b/core/src/main/java/google/registry/module/backend/BackendComponent.java index edd22b947..dc7693616 100644 --- a/core/src/main/java/google/registry/module/backend/BackendComponent.java +++ b/core/src/main/java/google/registry/module/backend/BackendComponent.java @@ -33,7 +33,7 @@ import google.registry.groups.GroupssettingsModule; import google.registry.keyring.KeyringModule; import google.registry.keyring.api.DummyKeyringModule; 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.monitoring.whitebox.StackdriverModule; import google.registry.persistence.PersistenceModule; @@ -70,9 +70,9 @@ import javax.inject.Singleton; GsonModule.class, KeyModule.class, KeyringModule.class, - KmsModule.class, NetHttpTransportModule.class, PersistenceModule.class, + SecretManagerKeyringModule.class, SecretManagerModule.class, ServerTridProviderModule.class, SheetsServiceModule.class, diff --git a/core/src/main/java/google/registry/module/frontend/FrontendComponent.java b/core/src/main/java/google/registry/module/frontend/FrontendComponent.java index 49e53e0b0..f37d370df 100644 --- a/core/src/main/java/google/registry/module/frontend/FrontendComponent.java +++ b/core/src/main/java/google/registry/module/frontend/FrontendComponent.java @@ -28,7 +28,7 @@ import google.registry.groups.GroupssettingsModule; import google.registry.keyring.KeyringModule; import google.registry.keyring.api.DummyKeyringModule; 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.monitoring.whitebox.StackdriverModule; import google.registry.privileges.secretmanager.SecretManagerModule; @@ -59,8 +59,8 @@ import javax.inject.Singleton; GsonModule.class, KeyModule.class, KeyringModule.class, - KmsModule.class, NetHttpTransportModule.class, + SecretManagerKeyringModule.class, SecretManagerModule.class, ServerTridProviderModule.class, StackdriverModule.class, diff --git a/core/src/main/java/google/registry/module/pubapi/PubApiComponent.java b/core/src/main/java/google/registry/module/pubapi/PubApiComponent.java index ef1d9c4ef..7ace50b01 100644 --- a/core/src/main/java/google/registry/module/pubapi/PubApiComponent.java +++ b/core/src/main/java/google/registry/module/pubapi/PubApiComponent.java @@ -27,7 +27,7 @@ import google.registry.groups.GroupssettingsModule; import google.registry.keyring.KeyringModule; import google.registry.keyring.api.DummyKeyringModule; 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.monitoring.whitebox.StackdriverModule; import google.registry.persistence.PersistenceModule; @@ -54,10 +54,10 @@ import javax.inject.Singleton; GsonModule.class, KeyModule.class, KeyringModule.class, - KmsModule.class, NetHttpTransportModule.class, PersistenceModule.class, PubApiRequestComponentModule.class, + SecretManagerKeyringModule.class, SecretManagerModule.class, ServerTridProviderModule.class, StackdriverModule.class, diff --git a/core/src/main/java/google/registry/module/tools/ToolsComponent.java b/core/src/main/java/google/registry/module/tools/ToolsComponent.java index 547db3bfd..4e0d26814 100644 --- a/core/src/main/java/google/registry/module/tools/ToolsComponent.java +++ b/core/src/main/java/google/registry/module/tools/ToolsComponent.java @@ -29,7 +29,7 @@ import google.registry.groups.GroupssettingsModule; import google.registry.keyring.KeyringModule; import google.registry.keyring.api.DummyKeyringModule; 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.monitoring.whitebox.StackdriverModule; import google.registry.privileges.secretmanager.SecretManagerModule; @@ -57,8 +57,8 @@ import javax.inject.Singleton; GsonModule.class, KeyModule.class, KeyringModule.class, - KmsModule.class, NetHttpTransportModule.class, + SecretManagerKeyringModule.class, SecretManagerModule.class, ServerTridProviderModule.class, StackdriverModule.class, diff --git a/core/src/main/java/google/registry/persistence/PersistenceComponent.java b/core/src/main/java/google/registry/persistence/PersistenceComponent.java index b918815c2..8c3a9a7b1 100644 --- a/core/src/main/java/google/registry/persistence/PersistenceComponent.java +++ b/core/src/main/java/google/registry/persistence/PersistenceComponent.java @@ -17,7 +17,7 @@ package google.registry.persistence; import dagger.Component; import google.registry.config.CredentialModule; 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.ReadOnlyReplicaJpaTm; import google.registry.persistence.transaction.JpaTransactionManager; @@ -32,8 +32,8 @@ import javax.persistence.EntityManagerFactory; modules = { ConfigModule.class, CredentialModule.class, - KmsModule.class, PersistenceModule.class, + SecretManagerKeyringModule.class, SecretManagerModule.class, UtilsModule.class }) diff --git a/core/src/main/java/google/registry/tools/RegistryToolComponent.java b/core/src/main/java/google/registry/tools/RegistryToolComponent.java index c0d4917fd..0fe2c5e6e 100644 --- a/core/src/main/java/google/registry/tools/RegistryToolComponent.java +++ b/core/src/main/java/google/registry/tools/RegistryToolComponent.java @@ -29,12 +29,11 @@ import google.registry.dns.writer.dnsupdate.DnsUpdateWriterModule; import google.registry.keyring.KeyringModule; import google.registry.keyring.api.DummyKeyringModule; 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.NomulusToolJpaTm; import google.registry.persistence.PersistenceModule.ReadOnlyReplicaJpaTm; import google.registry.persistence.transaction.JpaTransactionManager; -import google.registry.privileges.secretmanager.SecretManagerModule; import google.registry.rde.RdeModule; import google.registry.request.Modules.GsonModule; import google.registry.request.Modules.UrlConnectionServiceModule; @@ -70,13 +69,13 @@ import javax.inject.Singleton; GsonModule.class, KeyModule.class, KeyringModule.class, - KmsModule.class, + SecretManagerKeyringModule.class, LocalCredentialModule.class, PersistenceModule.class, RdeModule.class, RegistryToolDataflowModule.class, RequestFactoryModule.class, - SecretManagerModule.class, + google.registry.privileges.secretmanager.SecretManagerModule.class, UrlConnectionServiceModule.class, UrlFetchServiceModule.class, UserServiceModule.class, diff --git a/core/src/main/java/google/registry/tools/UpdateKeyringSecretCommand.java b/core/src/main/java/google/registry/tools/UpdateKeyringSecretCommand.java index 3034e5b02..a366e484d 100644 --- a/core/src/main/java/google/registry/tools/UpdateKeyringSecretCommand.java +++ b/core/src/main/java/google/registry/tools/UpdateKeyringSecretCommand.java @@ -20,7 +20,7 @@ import static google.registry.keyring.api.KeySerializer.deserializeString; import com.beust.jcommander.Parameter; 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.PathParameter; import java.nio.file.Files; @@ -33,7 +33,7 @@ import javax.inject.Inject; @Parameters(separators = " =", commandDescription = "Update values of secret in the keyring.") final class UpdateKeyringSecretCommand implements CommandWithRemoteApi { - @Inject KmsUpdater kmsUpdater; + @Inject SecretManagerKeyringUpdater secretManagerKeyringUpdater; @Inject UpdateKeyringSecretCommand() {} @@ -55,35 +55,35 @@ final class UpdateKeyringSecretCommand implements CommandWithRemoteApi { switch (keyringKeyName) { case BRDA_RECEIVER_PUBLIC_KEY: - kmsUpdater.setBrdaReceiverPublicKey(deserializePublicKey(input)); + secretManagerKeyringUpdater.setBrdaReceiverPublicKey(deserializePublicKey(input)); break; case BRDA_SIGNING_KEY_PAIR: - kmsUpdater.setBrdaSigningKey(deserializeKeyPair(input)); + secretManagerKeyringUpdater.setBrdaSigningKey(deserializeKeyPair(input)); break; case BRDA_SIGNING_PUBLIC_KEY: throw new IllegalArgumentException( "Can't update BRDA_SIGNING_PUBLIC_KEY directly." + " Must update public and private keys together using BRDA_SIGNING_KEY_PAIR."); case ICANN_REPORTING_PASSWORD: - kmsUpdater.setIcannReportingPassword(deserializeString(input)); + secretManagerKeyringUpdater.setIcannReportingPassword(deserializeString(input)); break; case JSON_CREDENTIAL: - kmsUpdater.setJsonCredential(deserializeString(input)); + secretManagerKeyringUpdater.setJsonCredential(deserializeString(input)); break; case MARKSDB_DNL_LOGIN_AND_PASSWORD: - kmsUpdater.setMarksdbDnlLoginAndPassword(deserializeString(input)); + secretManagerKeyringUpdater.setMarksdbDnlLoginAndPassword(deserializeString(input)); break; case MARKSDB_LORDN_PASSWORD: - kmsUpdater.setMarksdbLordnPassword(deserializeString(input)); + secretManagerKeyringUpdater.setMarksdbLordnPassword(deserializeString(input)); break; case MARKSDB_SMDRL_LOGIN_AND_PASSWORD: - kmsUpdater.setMarksdbSmdrlLoginAndPassword(deserializeString(input)); + secretManagerKeyringUpdater.setMarksdbSmdrlLoginAndPassword(deserializeString(input)); break; case RDE_RECEIVER_PUBLIC_KEY: - kmsUpdater.setRdeReceiverPublicKey(deserializePublicKey(input)); + secretManagerKeyringUpdater.setRdeReceiverPublicKey(deserializePublicKey(input)); break; case RDE_SIGNING_KEY_PAIR: - kmsUpdater.setRdeSigningKey(deserializeKeyPair(input)); + secretManagerKeyringUpdater.setRdeSigningKey(deserializeKeyPair(input)); break; case RDE_SIGNING_PUBLIC_KEY: 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. case RDE_SSH_CLIENT_PRIVATE_KEY: - kmsUpdater.setRdeSshClientPrivateKey(deserializeString(input)); + secretManagerKeyringUpdater.setRdeSshClientPrivateKey(deserializeString(input)); break; case RDE_SSH_CLIENT_PUBLIC_KEY: - kmsUpdater.setRdeSshClientPublicKey(deserializeString(input)); + secretManagerKeyringUpdater.setRdeSshClientPublicKey(deserializeString(input)); break; case RDE_STAGING_KEY_PAIR: - kmsUpdater.setRdeStagingKey(deserializeKeyPair(input)); + secretManagerKeyringUpdater.setRdeStagingKey(deserializeKeyPair(input)); break; case SAFE_BROWSING_API_KEY: - kmsUpdater.setSafeBrowsingAPIKey(deserializeString(input)); + secretManagerKeyringUpdater.setSafeBrowsingAPIKey(deserializeString(input)); break; case RDE_STAGING_PUBLIC_KEY: throw new IllegalArgumentException( @@ -112,7 +112,7 @@ final class UpdateKeyringSecretCommand implements CommandWithRemoteApi { + " Must update public and private keys together using RDE_STAGING_KEY_PAIR."); } - kmsUpdater.update(); + secretManagerKeyringUpdater.update(); } } diff --git a/core/src/test/java/google/registry/keyring/kms/GoogleJsonResponseExceptionHelper.java b/core/src/test/java/google/registry/keyring/kms/GoogleJsonResponseExceptionHelper.java deleted file mode 100644 index 2899ad68e..000000000 --- a/core/src/test/java/google/registry/keyring/kms/GoogleJsonResponseExceptionHelper.java +++ /dev/null @@ -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! - } - } -} diff --git a/core/src/test/java/google/registry/keyring/kms/KmsConnectionImplTest.java b/core/src/test/java/google/registry/keyring/kms/KmsConnectionImplTest.java deleted file mode 100644 index 0d0ae8eda..000000000 --- a/core/src/test/java/google/registry/keyring/kms/KmsConnectionImplTest.java +++ /dev/null @@ -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; - @Captor private ArgumentCaptor cryptoKey; - @Captor private ArgumentCaptor cryptoKeyVersion; - @Captor private ArgumentCaptor locationName; - @Captor private ArgumentCaptor keyRingName; - @Captor private ArgumentCaptor cryptoKeyName; - @Captor private ArgumentCaptor encryptRequest; - @Captor private ArgumentCaptor decryptRequest; - - @Captor - private ArgumentCaptor 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); - } -} diff --git a/core/src/test/java/google/registry/keyring/kms/KmsTestHelper.java b/core/src/test/java/google/registry/keyring/secretmanager/SecretManagerKeyringTestHelper.java similarity index 85% rename from core/src/test/java/google/registry/keyring/kms/KmsTestHelper.java rename to core/src/test/java/google/registry/keyring/secretmanager/SecretManagerKeyringTestHelper.java index bd8281023..147a13f72 100644 --- a/core/src/test/java/google/registry/keyring/kms/KmsTestHelper.java +++ b/core/src/test/java/google/registry/keyring/secretmanager/SecretManagerKeyringTestHelper.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.keyring.kms; +package google.registry.keyring.secretmanager; 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.BcPGPDigestCalculatorProvider; -/** Stores dummy values for test use in {@link KmsUpdaterTest}. */ -final class KmsTestHelper { +/** Stores dummy values for test use in {@link SecretManagerKeyringUpdaterTest}. */ +final class SecretManagerKeyringTestHelper { static final String DUMMY_CRYPTO_KEY_VERSION = "cheeseburger"; static final String DUMMY_ENCRYPTED_VALUE = "meow"; /** The contents of a dummy PGP private key stored in a file. */ 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 { return new BcPGPSecretKeyRing(PGPUtil.getDecoderStream(PGP_PRIVATE_KEYRING.openStream())); @@ -53,5 +54,5 @@ final class KmsTestHelper { .build(new char[0]))); } - private KmsTestHelper() {} + private SecretManagerKeyringTestHelper() {} } diff --git a/core/src/test/java/google/registry/keyring/kms/KmsUpdaterTest.java b/core/src/test/java/google/registry/keyring/secretmanager/SecretManagerKeyringUpdaterTest.java similarity index 84% rename from core/src/test/java/google/registry/keyring/kms/KmsUpdaterTest.java rename to core/src/test/java/google/registry/keyring/secretmanager/SecretManagerKeyringUpdaterTest.java index db8ce0fba..5bbce4c80 100644 --- a/core/src/test/java/google/registry/keyring/kms/KmsUpdaterTest.java +++ b/core/src/test/java/google/registry/keyring/secretmanager/SecretManagerKeyringUpdaterTest.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.keyring.kms; +package google.registry.keyring.secretmanager; 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.extension.RegisterExtension; -/** Unit tests for {@link KmsKeyring} and {@link KmsUpdater} */ -// TODO(2021-07-01): Rename this class along with KmsKeyring -public class KmsUpdaterTest { +/** Unit tests for {@link SecretManagerKeyring} and {@link SecretManagerKeyringUpdater} */ +public class SecretManagerKeyringUpdaterTest { @RegisterExtension public final BouncyCastleProviderExtension bouncy = new BouncyCastleProviderExtension(); private KeyringSecretStore secretStore; - private KmsUpdater updater; - private KmsKeyring keyring; + private SecretManagerKeyringUpdater updater; + private SecretManagerKeyring keyring; @BeforeEach void beforeEach() { secretStore = new KeyringSecretStore(new FakeSecretManagerClient()); - updater = new KmsUpdater(secretStore); - keyring = new KmsKeyring(secretStore); + updater = new SecretManagerKeyringUpdater(secretStore); + keyring = new SecretManagerKeyring(secretStore); } @Test @@ -66,7 +65,7 @@ public class KmsUpdaterTest { @Test void brdaReceiverKey() throws Exception { - PGPPublicKey publicKey = KmsTestHelper.getPublicKey(); + PGPPublicKey publicKey = SecretManagerKeyringTestHelper.getPublicKey(); updater.setBrdaReceiverPublicKey(publicKey).update(); assertThat(keyring.getBrdaReceiverKey().getFingerprint()).isEqualTo(publicKey.getFingerprint()); @@ -75,12 +74,14 @@ public class KmsUpdaterTest { @Test void brdaSigningKey() throws Exception { - PGPKeyPair keyPair = KmsTestHelper.getKeyPair(); + PGPKeyPair keyPair = SecretManagerKeyringTestHelper.getKeyPair(); updater.setBrdaSigningKey(keyPair).update(); assertThat(serializeKeyPair(keyring.getBrdaSigningKey())).isEqualTo(serializeKeyPair(keyPair)); - verifyPersistedSecret("brda-signing-private", serializeKeyPair(KmsTestHelper.getKeyPair())); - verifyPersistedSecret("brda-signing-public", serializePublicKey(KmsTestHelper.getPublicKey())); + verifyPersistedSecret( + "brda-signing-private", serializeKeyPair(SecretManagerKeyringTestHelper.getKeyPair())); + verifyPersistedSecret( + "brda-signing-public", serializePublicKey(SecretManagerKeyringTestHelper.getPublicKey())); } @Test @@ -130,16 +131,17 @@ public class KmsUpdaterTest { @Test void rdeReceiverKey() throws Exception { - PGPPublicKey publicKey = KmsTestHelper.getPublicKey(); + PGPPublicKey publicKey = SecretManagerKeyringTestHelper.getPublicKey(); updater.setRdeReceiverPublicKey(publicKey).update(); assertThat(keyring.getRdeReceiverKey().getFingerprint()).isEqualTo(publicKey.getFingerprint()); - verifyPersistedSecret("rde-receiver-public", serializePublicKey(KmsTestHelper.getPublicKey())); + verifyPersistedSecret( + "rde-receiver-public", serializePublicKey(SecretManagerKeyringTestHelper.getPublicKey())); } @Test void rdeSigningKey() throws Exception { - PGPKeyPair keyPair = KmsTestHelper.getKeyPair(); + PGPKeyPair keyPair = SecretManagerKeyringTestHelper.getKeyPair(); updater.setRdeSigningKey(keyPair).update(); assertThat(serializeKeyPair(keyring.getRdeSigningKey())).isEqualTo(serializeKeyPair(keyPair)); @@ -168,7 +170,7 @@ public class KmsUpdaterTest { @Test void rdeStagingKey() throws Exception { - PGPKeyPair keyPair = KmsTestHelper.getKeyPair(); + PGPKeyPair keyPair = SecretManagerKeyringTestHelper.getKeyPair(); updater.setRdeStagingKey(keyPair).update(); assertThat(serializePublicKey(keyring.getRdeStagingEncryptionKey())) @@ -181,7 +183,8 @@ public class KmsUpdaterTest { keyring.getRdeStagingEncryptionKey(), keyring.getRdeStagingDecryptionKey()))) .isEqualTo(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) { diff --git a/core/src/test/java/google/registry/persistence/PersistenceModuleTest.java b/core/src/test/java/google/registry/persistence/PersistenceModuleTest.java index 76a52c75c..1ae274547 100644 --- a/core/src/test/java/google/registry/persistence/PersistenceModuleTest.java +++ b/core/src/test/java/google/registry/persistence/PersistenceModuleTest.java @@ -21,7 +21,7 @@ import dagger.Component; import google.registry.config.CredentialModule; import google.registry.config.RegistryConfig.Config; 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.privileges.secretmanager.SecretManagerModule; import google.registry.testing.DatastoreEntityExtension; @@ -89,8 +89,8 @@ class PersistenceModuleTest { modules = { ConfigModule.class, CredentialModule.class, - KmsModule.class, PersistenceModule.class, + SecretManagerKeyringModule.class, SecretManagerModule.class, UtilsModule.class }) diff --git a/core/src/test/resources/google/registry/keyring/kms/pgp-private-keyring-registry.asc b/core/src/test/resources/google/registry/keyring/secretmanager/pgp-private-keyring-registry.asc similarity index 100% rename from core/src/test/resources/google/registry/keyring/kms/pgp-private-keyring-registry.asc rename to core/src/test/resources/google/registry/keyring/secretmanager/pgp-private-keyring-registry.asc diff --git a/core/src/test/resources/google/registry/keyring/kms/pgp-public-keyring.asc b/core/src/test/resources/google/registry/keyring/secretmanager/pgp-public-keyring.asc similarity index 100% rename from core/src/test/resources/google/registry/keyring/kms/pgp-public-keyring.asc rename to core/src/test/resources/google/registry/keyring/secretmanager/pgp-public-keyring.asc diff --git a/docs/configuration.md b/docs/configuration.md index 4e73dbc31..8d602ad1e 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -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 configure a production registry system, you will need to either use the -KmsKeyring or write your own replacement module using `DummyKeyringModule` for -guidance. Such a module should provide either an instance of -`InMemoryKeyring` or your own custom implementation of `Keyring`. +SecretManagerKeyring or write your own replacement module using +`DummyKeyringModule` for guidance. Such a module should provide either an +instance of `InMemoryKeyring` or your own custom implementation of `Keyring`. 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 -KMS to configure accordingly, for example: +appropriate parameters. Use an `activeKeyring` of "CSM" with a project id for +SecretManager to configure accordingly, for example: keyring: - activeKeyring: KMS - kms: - projectId: acme-registry-keys + activeKeyring: CSM ## 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" command specified above. -### Cloud KMS +### Cloud SecretManager -You'll need to choose a project to host the KMS keyring. Best practice is to -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" +You'll need to enable the SecretManager API in your project. #### 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 above when creating database user accounts. These should currently be stored 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. $ 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 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 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 keyring: - activeKeyring: KMS - kms: - projectId: KEYS_PROJECT_ID + activeKeyring: CSM registryTool: clientId: TOOLS_OAUTH_CLIENT_ID diff --git a/docs/gradle.lockfile b/docs/gradle.lockfile index d2581fc70..0f1323f6c 100644 --- a/docs/gradle.lockfile +++ b/docs/gradle.lockfile @@ -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-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-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-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 diff --git a/services/backend/gradle.lockfile b/services/backend/gradle.lockfile index f215c4019..051aceced 100644 --- a/services/backend/gradle.lockfile +++ b/services/backend/gradle.lockfile @@ -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-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-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-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 diff --git a/services/default/gradle.lockfile b/services/default/gradle.lockfile index f215c4019..051aceced 100644 --- a/services/default/gradle.lockfile +++ b/services/default/gradle.lockfile @@ -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-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-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-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 diff --git a/services/pubapi/gradle.lockfile b/services/pubapi/gradle.lockfile index f215c4019..051aceced 100644 --- a/services/pubapi/gradle.lockfile +++ b/services/pubapi/gradle.lockfile @@ -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-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-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-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 diff --git a/services/tools/gradle.lockfile b/services/tools/gradle.lockfile index f215c4019..051aceced 100644 --- a/services/tools/gradle.lockfile +++ b/services/tools/gradle.lockfile @@ -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-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-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-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