mirror of
https://github.com/google/nomulus.git
synced 2025-04-30 03:57:51 +02:00
Remove KmsSecret model entities (#1252)
* Remove KmsSecret model entities Now that we have been using the SecretManager for almost a month now, remove the KmsSecret and KmsSecretRevision entities from Java code base. A follow-up PR will drop the relevant tables in the schema. Also removed a few unused classes in the beam package.
This commit is contained in:
parent
4a6fd65b0c
commit
50f3139b98
20 changed files with 3 additions and 622 deletions
|
@ -74,8 +74,6 @@ def fragileTestPatterns = [
|
||||||
"google/registry/cron/TldFanoutActionTest.*",
|
"google/registry/cron/TldFanoutActionTest.*",
|
||||||
// Test Datastore inexplicably aborts transaction.
|
// Test Datastore inexplicably aborts transaction.
|
||||||
"google/registry/model/tmch/ClaimsListShardTest.*",
|
"google/registry/model/tmch/ClaimsListShardTest.*",
|
||||||
// Creates large object (64MBytes), occasionally throws OOM error.
|
|
||||||
"google/registry/model/server/KmsSecretRevisionTest.*",
|
|
||||||
// Changes cache timeouts and for some reason appears to have contention
|
// Changes cache timeouts and for some reason appears to have contention
|
||||||
// with other tests.
|
// with other tests.
|
||||||
"google/registry/whois/WhoisCommandFactoryTest.*",
|
"google/registry/whois/WhoisCommandFactoryTest.*",
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
// Copyright 2020 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.beam.initsql;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
|
|
||||||
import com.google.api.services.cloudkms.v1.model.DecryptRequest;
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import google.registry.config.RegistryConfig.Config;
|
|
||||||
import google.registry.keyring.kms.KmsConnection;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Base64;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decrypts data using Cloud KMS, with the same crypto key with which Cloud SQL credential files on
|
|
||||||
* GCS was encrypted. See {@link BackupPaths#getCloudSQLCredentialFilePatterns} for more
|
|
||||||
* information.
|
|
||||||
*/
|
|
||||||
public class CloudSqlCredentialDecryptor {
|
|
||||||
|
|
||||||
private static final String CRYPTO_KEY_NAME = "nomulus-tool-key";
|
|
||||||
private final KmsConnection kmsConnection;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
CloudSqlCredentialDecryptor(@Config("beamKmsConnection") KmsConnection kmsConnection) {
|
|
||||||
this.kmsConnection = kmsConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String decrypt(String data) {
|
|
||||||
checkArgument(!Strings.isNullOrEmpty(data), "Null or empty data.");
|
|
||||||
byte[] ciphertext = Base64.getDecoder().decode(data);
|
|
||||||
// Re-encode for Cloud KMS JSON REST API, invoked through kmsConnection.
|
|
||||||
String urlSafeCipherText = new DecryptRequest().encodeCiphertext(ciphertext).getCiphertext();
|
|
||||||
return new String(
|
|
||||||
kmsConnection.decrypt(CRYPTO_KEY_NAME, urlSafeCipherText), StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
// Copyright 2020 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.beam.initsql;
|
|
||||||
|
|
||||||
import com.google.auto.value.AutoValue;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information needed to connect to a database, including JDBC URL, user name, password, and in the
|
|
||||||
* case of Cloud SQL, the database instance's name.
|
|
||||||
*/
|
|
||||||
@AutoValue
|
|
||||||
abstract class SqlAccessInfo {
|
|
||||||
|
|
||||||
abstract String jdbcUrl();
|
|
||||||
|
|
||||||
abstract String user();
|
|
||||||
|
|
||||||
abstract String password();
|
|
||||||
|
|
||||||
abstract Optional<String> cloudSqlInstanceName();
|
|
||||||
|
|
||||||
public static SqlAccessInfo createCloudSqlAccessInfo(
|
|
||||||
String sqlInstanceName, String username, String password) {
|
|
||||||
return new AutoValue_SqlAccessInfo(
|
|
||||||
"jdbc:postgresql://google/postgres", username, password, Optional.of(sqlInstanceName));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SqlAccessInfo createLocalSqlAccessInfo(
|
|
||||||
String jdbcUrl, String username, String password) {
|
|
||||||
return new AutoValue_SqlAccessInfo(jdbcUrl, username, password, Optional.empty());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -28,14 +28,8 @@ import org.bouncycastle.openpgp.PGPKeyPair;
|
||||||
import org.bouncycastle.openpgp.PGPPrivateKey;
|
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 encrypted secrets in Datastore and decrypts them
|
// TODO(2021-08-01): rename this class to SecretManagerKeyring and update config files.
|
||||||
* using encryption keys stored in Cloud KMS.
|
|
||||||
*
|
|
||||||
* @see <a href="https://cloud.google.com/kms/docs/">Google Cloud Key Management Service
|
|
||||||
* Documentation</a>
|
|
||||||
*/
|
|
||||||
// TODO(2021-07-01): rename this class to SecretManagerKeyring and delete KmsSecretRevision
|
|
||||||
public class KmsKeyring implements Keyring {
|
public class KmsKeyring implements Keyring {
|
||||||
|
|
||||||
/** Key labels for private key secrets. */
|
/** Key labels for private key secrets. */
|
||||||
|
|
|
@ -43,8 +43,6 @@ import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.registry.label.PremiumList;
|
import google.registry.model.registry.label.PremiumList;
|
||||||
import google.registry.model.registry.label.ReservedList;
|
import google.registry.model.registry.label.ReservedList;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.server.KmsSecret;
|
|
||||||
import google.registry.model.server.KmsSecretRevision;
|
|
||||||
import google.registry.model.server.Lock;
|
import google.registry.model.server.Lock;
|
||||||
import google.registry.model.server.ServerSecret;
|
import google.registry.model.server.ServerSecret;
|
||||||
import google.registry.model.tmch.ClaimsList;
|
import google.registry.model.tmch.ClaimsList;
|
||||||
|
@ -88,8 +86,6 @@ public final class EntityClasses {
|
||||||
HistoryEntry.class,
|
HistoryEntry.class,
|
||||||
HostHistory.class,
|
HostHistory.class,
|
||||||
HostResource.class,
|
HostResource.class,
|
||||||
KmsSecret.class,
|
|
||||||
KmsSecretRevision.class,
|
|
||||||
LastSqlTransaction.class,
|
LastSqlTransaction.class,
|
||||||
Lock.class,
|
Lock.class,
|
||||||
PollMessage.class,
|
PollMessage.class,
|
||||||
|
|
|
@ -1,57 +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.model.server;
|
|
||||||
|
|
||||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
|
||||||
|
|
||||||
import com.googlecode.objectify.Key;
|
|
||||||
import com.googlecode.objectify.annotation.Entity;
|
|
||||||
import com.googlecode.objectify.annotation.Id;
|
|
||||||
import com.googlecode.objectify.annotation.Parent;
|
|
||||||
import google.registry.model.ImmutableObject;
|
|
||||||
import google.registry.model.annotations.InCrossTld;
|
|
||||||
import google.registry.model.annotations.ReportedOn;
|
|
||||||
import google.registry.model.common.EntityGroupRoot;
|
|
||||||
import google.registry.schema.replay.DatastoreOnlyEntity;
|
|
||||||
|
|
||||||
/** Pointer to the latest {@link KmsSecretRevision}. */
|
|
||||||
@Entity
|
|
||||||
@ReportedOn
|
|
||||||
@InCrossTld
|
|
||||||
public class KmsSecret extends ImmutableObject implements DatastoreOnlyEntity {
|
|
||||||
|
|
||||||
/** The unique name of this {@link KmsSecret}. */
|
|
||||||
@Id String name;
|
|
||||||
|
|
||||||
@Parent Key<EntityGroupRoot> parent = getCrossTldKey();
|
|
||||||
|
|
||||||
/** The pointer to the latest {@link KmsSecretRevision}. */
|
|
||||||
Key<KmsSecretRevision> latestRevision;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Key<KmsSecretRevision> getLatestRevision() {
|
|
||||||
return latestRevision;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static KmsSecret create(String name, KmsSecretRevision latestRevision) {
|
|
||||||
KmsSecret instance = new KmsSecret();
|
|
||||||
instance.name = name;
|
|
||||||
instance.latestRevision = Key.create(latestRevision);
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,162 +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.model.server;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
|
||||||
|
|
||||||
import com.googlecode.objectify.Key;
|
|
||||||
import com.googlecode.objectify.annotation.Entity;
|
|
||||||
import com.googlecode.objectify.annotation.Id;
|
|
||||||
import com.googlecode.objectify.annotation.Ignore;
|
|
||||||
import com.googlecode.objectify.annotation.OnLoad;
|
|
||||||
import com.googlecode.objectify.annotation.Parent;
|
|
||||||
import google.registry.model.Buildable;
|
|
||||||
import google.registry.model.CreateAutoTimestamp;
|
|
||||||
import google.registry.model.ImmutableObject;
|
|
||||||
import google.registry.model.annotations.InCrossTld;
|
|
||||||
import google.registry.model.annotations.ReportedOn;
|
|
||||||
import google.registry.schema.replay.NonReplicatedEntity;
|
|
||||||
import javax.persistence.Column;
|
|
||||||
import javax.persistence.Index;
|
|
||||||
import javax.persistence.PostLoad;
|
|
||||||
import javax.persistence.Table;
|
|
||||||
import javax.persistence.Transient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An encrypted value.
|
|
||||||
*
|
|
||||||
* <p>Used to store passwords and other sensitive information in Datastore. Multiple versions of a
|
|
||||||
* {@link KmsSecretRevision} may be persisted but only the latest version is primary. A key to the
|
|
||||||
* primary version is stored by {@link KmsSecret#latestRevision}.
|
|
||||||
*
|
|
||||||
* <p>The value can be encrypted and decrypted using Cloud KMS.
|
|
||||||
*
|
|
||||||
* <p>Note that the primary key of this entity is {@link #revisionKey}, which is auto-generated by
|
|
||||||
* the database. So, if a retry of insertion happens after the previous attempt unexpectedly
|
|
||||||
* succeeds, we will end up with having two exact same revisions that differ only by revisionKey.
|
|
||||||
* This is fine though, because we only use the revision with the highest revisionKey.
|
|
||||||
*
|
|
||||||
* <p>TODO(b/177567432): remove Datastore-specific fields post-Registry-3.0-migration and rename to
|
|
||||||
* KmsSecret.
|
|
||||||
*
|
|
||||||
* @see <a href="https://cloud.google.com/kms/docs/">Google Cloud Key Management Service
|
|
||||||
* Documentation</a>
|
|
||||||
* @see google.registry.keyring.kms.KmsKeyring
|
|
||||||
*/
|
|
||||||
@Entity
|
|
||||||
@ReportedOn
|
|
||||||
@javax.persistence.Entity(name = "KmsSecret")
|
|
||||||
@Table(indexes = {@Index(columnList = "secretName")})
|
|
||||||
@InCrossTld
|
|
||||||
public class KmsSecretRevision extends ImmutableObject implements NonReplicatedEntity {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum allowable secret size. Although Datastore allows entities up to 1 MB in size,
|
|
||||||
* BigQuery imports of Datastore backups limit individual columns (entity attributes) to 64 KB.
|
|
||||||
*/
|
|
||||||
private static final int MAX_SECRET_SIZE_BYTES = 64 * 1024 * 1024;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The revision of this secret.
|
|
||||||
*
|
|
||||||
* <p>TODO(b/177567432): change name of the variable to revisionId once we're off Datastore
|
|
||||||
*/
|
|
||||||
@Id
|
|
||||||
@javax.persistence.Id
|
|
||||||
@Column(name = "revisionId")
|
|
||||||
long revisionKey;
|
|
||||||
|
|
||||||
/** The parent {@link KmsSecret} which contains metadata about this {@link KmsSecretRevision}. */
|
|
||||||
@Parent @Transient Key<KmsSecret> parent;
|
|
||||||
@Column(nullable = false)
|
|
||||||
@Ignore
|
|
||||||
String secretName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the {@code cryptoKeyVersion} associated with this {@link KmsSecretRevision}.
|
|
||||||
*
|
|
||||||
* <p>TODO: change name of the variable to cryptoKeyVersionName once we're off Datastore
|
|
||||||
*
|
|
||||||
* @see <a
|
|
||||||
* href="https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys.cryptoKeyVersions">projects.locations.keyRings.cryptoKeys.cryptoKeyVersions</a>
|
|
||||||
*/
|
|
||||||
@Column(nullable = false, name = "cryptoKeyVersionName")
|
|
||||||
String kmsCryptoKeyVersionName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The base64-encoded encrypted value of this {@link KmsSecretRevision} as returned by the Cloud
|
|
||||||
* KMS API.
|
|
||||||
*
|
|
||||||
* @see <a
|
|
||||||
* href="https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys/encrypt">projects.locations.keyRings.cryptoKeys.encrypt</a>
|
|
||||||
*/
|
|
||||||
@Column(nullable = false)
|
|
||||||
String encryptedValue;
|
|
||||||
|
|
||||||
/** An automatically managed creation timestamp. */
|
|
||||||
@Column(nullable = false)
|
|
||||||
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
|
||||||
|
|
||||||
public String getKmsCryptoKeyVersionName() {
|
|
||||||
return kmsCryptoKeyVersionName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEncryptedValue() {
|
|
||||||
return encryptedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When loading from SQL, fill out the Datastore-specific field
|
|
||||||
@PostLoad
|
|
||||||
void postLoad() {
|
|
||||||
parent = Key.create(getCrossTldKey(), KmsSecret.class, secretName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// When loading from Datastore, fill out the SQL-specific field
|
|
||||||
@OnLoad
|
|
||||||
void onLoad() {
|
|
||||||
secretName = parent.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A builder for constructing {@link KmsSecretRevision} entities, since they are immutable. */
|
|
||||||
public static class Builder extends Buildable.Builder<KmsSecretRevision> {
|
|
||||||
|
|
||||||
public Builder setKmsCryptoKeyVersionName(String kmsCryptoKeyVersionName) {
|
|
||||||
getInstance().kmsCryptoKeyVersionName = kmsCryptoKeyVersionName;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setEncryptedValue(String encryptedValue) {
|
|
||||||
checkArgument(
|
|
||||||
encryptedValue.length() <= MAX_SECRET_SIZE_BYTES,
|
|
||||||
"Secret is greater than %s bytes",
|
|
||||||
MAX_SECRET_SIZE_BYTES);
|
|
||||||
|
|
||||||
getInstance().encryptedValue = encryptedValue;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the parent {@link KmsSecret}.
|
|
||||||
*
|
|
||||||
* <p>The secret may not exist yet, so it is referred to by name rather than by reference.
|
|
||||||
*/
|
|
||||||
public Builder setParent(String secretName) {
|
|
||||||
getInstance().parent = Key.create(getCrossTldKey(), KmsSecret.class, secretName);
|
|
||||||
getInstance().secretName = secretName;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
// Copyright 2020 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.model.server;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
|
||||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
|
||||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link KmsSecretRevision} DAO for Cloud SQL.
|
|
||||||
*
|
|
||||||
* <p>TODO(b/177567432): Rename this class to KmsSecretDao after migrating to Cloud SQL.
|
|
||||||
*/
|
|
||||||
public class KmsSecretRevisionSqlDao {
|
|
||||||
|
|
||||||
private KmsSecretRevisionSqlDao() {}
|
|
||||||
|
|
||||||
/** Saves the given KMS secret revision. */
|
|
||||||
public static void save(KmsSecretRevision kmsSecretRevision) {
|
|
||||||
checkArgumentNotNull(kmsSecretRevision, "kmsSecretRevision cannot be null");
|
|
||||||
jpaTm().assertInTransaction();
|
|
||||||
jpaTm().put(kmsSecretRevision);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the latest revision for the secret name given, or absent if nonexistent. */
|
|
||||||
public static Optional<KmsSecretRevision> getLatestRevision(String secretName) {
|
|
||||||
checkArgument(!isNullOrEmpty(secretName), "secretName cannot be null or empty");
|
|
||||||
jpaTm().assertInTransaction();
|
|
||||||
return jpaTm()
|
|
||||||
.query(
|
|
||||||
"FROM KmsSecret ks WHERE ks.revisionKey IN (SELECT MAX(revisionKey) FROM "
|
|
||||||
+ "KmsSecret subKs WHERE subKs.secretName = :secretName)",
|
|
||||||
KmsSecretRevision.class)
|
|
||||||
.setParameter("secretName", secretName)
|
|
||||||
.getResultStream()
|
|
||||||
.findFirst();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -37,7 +37,6 @@ import google.registry.model.index.ForeignKeyIndex.ForeignKeyContactIndex;
|
||||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyDomainIndex;
|
import google.registry.model.index.ForeignKeyIndex.ForeignKeyDomainIndex;
|
||||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyHostIndex;
|
import google.registry.model.index.ForeignKeyIndex.ForeignKeyHostIndex;
|
||||||
import google.registry.model.ofy.DatastoreTransactionManager;
|
import google.registry.model.ofy.DatastoreTransactionManager;
|
||||||
import google.registry.model.server.KmsSecret;
|
|
||||||
import google.registry.model.tmch.ClaimsList.ClaimsListSingleton;
|
import google.registry.model.tmch.ClaimsList.ClaimsListSingleton;
|
||||||
import google.registry.persistence.JpaRetries;
|
import google.registry.persistence.JpaRetries;
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
|
@ -94,8 +93,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
||||||
EppResourceIndex.class,
|
EppResourceIndex.class,
|
||||||
ForeignKeyContactIndex.class,
|
ForeignKeyContactIndex.class,
|
||||||
ForeignKeyDomainIndex.class,
|
ForeignKeyDomainIndex.class,
|
||||||
ForeignKeyHostIndex.class,
|
ForeignKeyHostIndex.class);
|
||||||
KmsSecret.class);
|
|
||||||
|
|
||||||
// EntityManagerFactory is thread safe.
|
// EntityManagerFactory is thread safe.
|
||||||
private final EntityManagerFactory emf;
|
private final EntityManagerFactory emf;
|
||||||
|
|
|
@ -65,7 +65,6 @@
|
||||||
<class>google.registry.model.registry.Registry</class>
|
<class>google.registry.model.registry.Registry</class>
|
||||||
<class>google.registry.model.reporting.DomainTransactionRecord</class>
|
<class>google.registry.model.reporting.DomainTransactionRecord</class>
|
||||||
<class>google.registry.model.reporting.Spec11ThreatMatch</class>
|
<class>google.registry.model.reporting.Spec11ThreatMatch</class>
|
||||||
<class>google.registry.model.server.KmsSecretRevision</class>
|
|
||||||
<class>google.registry.model.server.Lock</class>
|
<class>google.registry.model.server.Lock</class>
|
||||||
<class>google.registry.model.server.ServerSecret</class>
|
<class>google.registry.model.server.ServerSecret</class>
|
||||||
<class>google.registry.model.smd.SignedMarkRevocationList</class>
|
<class>google.registry.model.smd.SignedMarkRevocationList</class>
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
// Copyright 2020 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.model.server;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
|
||||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
|
||||||
|
|
||||||
import google.registry.persistence.transaction.JpaTestRules;
|
|
||||||
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageExtension;
|
|
||||||
import google.registry.testing.DatastoreEntityExtension;
|
|
||||||
import google.registry.testing.FakeClock;
|
|
||||||
import java.util.Optional;
|
|
||||||
import org.junit.jupiter.api.Order;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
|
||||||
|
|
||||||
/** Tests for {@link google.registry.model.server.KmsSecretRevisionSqlDao}. */
|
|
||||||
public class KmsSecretRevisionSqlDaoTest {
|
|
||||||
|
|
||||||
private final FakeClock fakeClock = new FakeClock();
|
|
||||||
|
|
||||||
@RegisterExtension
|
|
||||||
@Order(value = 1)
|
|
||||||
DatastoreEntityExtension datastoreEntityExtension = new DatastoreEntityExtension();
|
|
||||||
|
|
||||||
@RegisterExtension
|
|
||||||
JpaIntegrationWithCoverageExtension jpa =
|
|
||||||
new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveAndRetrieve() {
|
|
||||||
KmsSecretRevision revision = createRevision();
|
|
||||||
jpaTm().transact(() -> KmsSecretRevisionSqlDao.save(revision));
|
|
||||||
Optional<KmsSecretRevision> fromSql =
|
|
||||||
jpaTm().transact(() -> KmsSecretRevisionSqlDao.getLatestRevision("secretName"));
|
|
||||||
assertThat(fromSql.isPresent()).isTrue();
|
|
||||||
assertAboutImmutableObjects().that(revision).isEqualExceptFields(fromSql.get(), "creationTime");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testMultipleRevisions() {
|
|
||||||
KmsSecretRevision revision = createRevision();
|
|
||||||
jpaTm().transact(() -> KmsSecretRevisionSqlDao.save(revision));
|
|
||||||
|
|
||||||
KmsSecretRevision secondRevision = createRevision();
|
|
||||||
secondRevision.encryptedValue = "someOtherValue";
|
|
||||||
jpaTm().transact(() -> KmsSecretRevisionSqlDao.save(secondRevision));
|
|
||||||
|
|
||||||
Optional<KmsSecretRevision> fromSql =
|
|
||||||
jpaTm().transact(() -> KmsSecretRevisionSqlDao.getLatestRevision("secretName"));
|
|
||||||
assertThat(fromSql.isPresent()).isTrue();
|
|
||||||
assertThat(fromSql.get().getEncryptedValue()).isEqualTo("someOtherValue");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testNonexistent() {
|
|
||||||
KmsSecretRevision revision = createRevision();
|
|
||||||
jpaTm().transact(() -> KmsSecretRevisionSqlDao.save(revision));
|
|
||||||
assertThat(
|
|
||||||
jpaTm()
|
|
||||||
.transact(() -> KmsSecretRevisionSqlDao.getLatestRevision("someOtherSecretName"))
|
|
||||||
.isPresent())
|
|
||||||
.isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
private KmsSecretRevision createRevision() {
|
|
||||||
return new KmsSecretRevision.Builder()
|
|
||||||
.setEncryptedValue("encrypted")
|
|
||||||
.setKmsCryptoKeyVersionName("version")
|
|
||||||
.setParent("secretName")
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,68 +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.model.server;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
|
||||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import google.registry.testing.AppEngineExtension;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
|
||||||
|
|
||||||
/** Unit tests for {@link google.registry.model.server.KmsSecretRevision}. */
|
|
||||||
public class KmsSecretRevisionTest {
|
|
||||||
|
|
||||||
@RegisterExtension
|
|
||||||
public final AppEngineExtension appEngine =
|
|
||||||
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
|
||||||
|
|
||||||
private KmsSecretRevision secretRevision;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void beforeEach() {
|
|
||||||
secretRevision =
|
|
||||||
persistResource(
|
|
||||||
new KmsSecretRevision.Builder()
|
|
||||||
.setKmsCryptoKeyVersionName("foo")
|
|
||||||
.setParent("bar")
|
|
||||||
.setEncryptedValue("blah")
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test_setEncryptedValue_tooLong_throwsException() {
|
|
||||||
IllegalArgumentException thrown =
|
|
||||||
assertThrows(
|
|
||||||
IllegalArgumentException.class,
|
|
||||||
() ->
|
|
||||||
secretRevision =
|
|
||||||
persistResource(
|
|
||||||
new KmsSecretRevision.Builder()
|
|
||||||
.setKmsCryptoKeyVersionName("foo")
|
|
||||||
.setParent("bar")
|
|
||||||
.setEncryptedValue(Strings.repeat("a", 64 * 1024 * 1024 + 1))
|
|
||||||
.build()));
|
|
||||||
assertThat(thrown).hasMessageThat().contains("Secret is greater than 67108864 bytes");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testPersistence() {
|
|
||||||
assertThat(ofyTm().loadByEntity(secretRevision)).isEqualTo(secretRevision);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +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.model.server;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
|
||||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
|
||||||
|
|
||||||
import google.registry.testing.AppEngineExtension;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
|
||||||
|
|
||||||
public class KmsSecretTest {
|
|
||||||
|
|
||||||
@RegisterExtension
|
|
||||||
public final AppEngineExtension appEngine =
|
|
||||||
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
|
||||||
|
|
||||||
private KmsSecret secret;
|
|
||||||
private KmsSecretRevision secretRevision;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
secretRevision =
|
|
||||||
persistResource(
|
|
||||||
new KmsSecretRevision.Builder()
|
|
||||||
.setKmsCryptoKeyVersionName("foo")
|
|
||||||
.setParent("bar")
|
|
||||||
.setEncryptedValue("blah")
|
|
||||||
.build());
|
|
||||||
|
|
||||||
secret = persistResource(KmsSecret.create("someSecret", secretRevision));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testPersistence() {
|
|
||||||
assertThat(ofyTm().loadByEntity(secret)).isEqualTo(secret);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -30,7 +30,6 @@ import google.registry.model.registry.RegistryLockDaoTest;
|
||||||
import google.registry.model.registry.RegistryTest;
|
import google.registry.model.registry.RegistryTest;
|
||||||
import google.registry.model.registry.label.ReservedListDaoTest;
|
import google.registry.model.registry.label.ReservedListDaoTest;
|
||||||
import google.registry.model.reporting.Spec11ThreatMatchTest;
|
import google.registry.model.reporting.Spec11ThreatMatchTest;
|
||||||
import google.registry.model.server.KmsSecretRevisionSqlDaoTest;
|
|
||||||
import google.registry.model.server.LockTest;
|
import google.registry.model.server.LockTest;
|
||||||
import google.registry.model.server.ServerSecretTest;
|
import google.registry.model.server.ServerSecretTest;
|
||||||
import google.registry.model.smd.SignedMarkRevocationListDaoTest;
|
import google.registry.model.smd.SignedMarkRevocationListDaoTest;
|
||||||
|
@ -89,7 +88,6 @@ import org.junit.runner.RunWith;
|
||||||
DomainBaseSqlTest.class,
|
DomainBaseSqlTest.class,
|
||||||
DomainHistoryTest.class,
|
DomainHistoryTest.class,
|
||||||
HostHistoryTest.class,
|
HostHistoryTest.class,
|
||||||
KmsSecretRevisionSqlDaoTest.class,
|
|
||||||
LockTest.class,
|
LockTest.class,
|
||||||
PollMessageTest.class,
|
PollMessageTest.class,
|
||||||
PremiumListDaoTest.class,
|
PremiumListDaoTest.class,
|
||||||
|
|
|
@ -116,7 +116,6 @@ public class ReplayExtension implements BeforeEachCallback, AfterEachCallback {
|
||||||
"PremiumListEntry",
|
"PremiumListEntry",
|
||||||
"ReservedList",
|
"ReservedList",
|
||||||
"RdeRevision",
|
"RdeRevision",
|
||||||
"KmsSecretRevision",
|
|
||||||
"ServerSecret",
|
"ServerSecret",
|
||||||
"SignedMarkRevocationList",
|
"SignedMarkRevocationList",
|
||||||
"ClaimsListShard",
|
"ClaimsListShard",
|
||||||
|
|
|
@ -11,8 +11,6 @@ ForeignKeyDomainIndex
|
||||||
ForeignKeyHostIndex
|
ForeignKeyHostIndex
|
||||||
HistoryEntry
|
HistoryEntry
|
||||||
HostResource
|
HostResource
|
||||||
KmsSecret
|
|
||||||
KmsSecretRevision
|
|
||||||
LastSqlTransaction
|
LastSqlTransaction
|
||||||
Modification
|
Modification
|
||||||
OneTime
|
OneTime
|
||||||
|
|
|
@ -2,8 +2,6 @@ ClaimsList
|
||||||
ClaimsListSingleton
|
ClaimsListSingleton
|
||||||
Cursor
|
Cursor
|
||||||
DatabaseMigrationStateSchedule
|
DatabaseMigrationStateSchedule
|
||||||
KmsSecret
|
|
||||||
KmsSecretRevision
|
|
||||||
PremiumList
|
PremiumList
|
||||||
PremiumListEntry
|
PremiumListEntry
|
||||||
PremiumListRevision
|
PremiumListRevision
|
||||||
|
|
|
@ -8,8 +8,6 @@ ForeignKeyDomainIndex
|
||||||
ForeignKeyHostIndex
|
ForeignKeyHostIndex
|
||||||
HistoryEntry
|
HistoryEntry
|
||||||
HostResource
|
HostResource
|
||||||
KmsSecret
|
|
||||||
KmsSecretRevision
|
|
||||||
Modification
|
Modification
|
||||||
OneTime
|
OneTime
|
||||||
PollMessage
|
PollMessage
|
||||||
|
|
|
@ -825,18 +825,6 @@ enum google.registry.model.reporting.HistoryEntry$Type {
|
||||||
RDE_IMPORT;
|
RDE_IMPORT;
|
||||||
SYNTHETIC;
|
SYNTHETIC;
|
||||||
}
|
}
|
||||||
class google.registry.model.server.KmsSecret {
|
|
||||||
@Id java.lang.String name;
|
|
||||||
@Parent com.googlecode.objectify.Key<google.registry.model.common.EntityGroupRoot> parent;
|
|
||||||
com.googlecode.objectify.Key<google.registry.model.server.KmsSecretRevision> latestRevision;
|
|
||||||
}
|
|
||||||
class google.registry.model.server.KmsSecretRevision {
|
|
||||||
@Id long revisionKey;
|
|
||||||
@Parent com.googlecode.objectify.Key<google.registry.model.server.KmsSecret> parent;
|
|
||||||
google.registry.model.CreateAutoTimestamp creationTime;
|
|
||||||
java.lang.String encryptedValue;
|
|
||||||
java.lang.String kmsCryptoKeyVersionName;
|
|
||||||
}
|
|
||||||
class google.registry.model.server.Lock {
|
class google.registry.model.server.Lock {
|
||||||
@Id java.lang.String lockId;
|
@Id java.lang.String lockId;
|
||||||
java.lang.String requestLogId;
|
java.lang.String requestLogId;
|
||||||
|
|
|
@ -491,15 +491,6 @@
|
||||||
primary key (host_repo_id, history_revision_id)
|
primary key (host_repo_id, history_revision_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
create table "KmsSecret" (
|
|
||||||
revision_id int8 not null,
|
|
||||||
creation_time timestamptz not null,
|
|
||||||
encrypted_value text not null,
|
|
||||||
crypto_key_version_name text not null,
|
|
||||||
secret_name text not null,
|
|
||||||
primary key (revision_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
create table "Lock" (
|
create table "Lock" (
|
||||||
resource_name text not null,
|
resource_name text not null,
|
||||||
scope text not null,
|
scope text not null,
|
||||||
|
@ -806,7 +797,6 @@ create index IDX1iy7njgb7wjmj9piml4l2g0qi on "HostHistory" (history_registrar_id
|
||||||
create index IDXkkwbwcwvrdkkqothkiye4jiff on "HostHistory" (host_name);
|
create index IDXkkwbwcwvrdkkqothkiye4jiff on "HostHistory" (host_name);
|
||||||
create index IDXknk8gmj7s47q56cwpa6rmpt5l on "HostHistory" (history_type);
|
create index IDXknk8gmj7s47q56cwpa6rmpt5l on "HostHistory" (history_type);
|
||||||
create index IDX67qwkjtlq5q8dv6egtrtnhqi7 on "HostHistory" (history_modification_time);
|
create index IDX67qwkjtlq5q8dv6egtrtnhqi7 on "HostHistory" (history_modification_time);
|
||||||
create index IDXli9nil3s4t4p21i3xluvvilb7 on "KmsSecret" (secret_name);
|
|
||||||
create index IDXe7wu46c7wpvfmfnj4565abibp on "PollMessage" (registrar_id);
|
create index IDXe7wu46c7wpvfmfnj4565abibp on "PollMessage" (registrar_id);
|
||||||
create index IDXaydgox62uno9qx8cjlj5lauye on "PollMessage" (event_time);
|
create index IDXaydgox62uno9qx8cjlj5lauye on "PollMessage" (event_time);
|
||||||
create index premiumlist_name_idx on "PremiumList" (name);
|
create index premiumlist_name_idx on "PremiumList" (name);
|
||||||
|
|
Loading…
Add table
Reference in a new issue