From 8280106493496f035a0a773d3f9bdb9e5c85e82c Mon Sep 17 00:00:00 2001 From: Chris Eager Date: Thu, 19 Dec 2024 18:09:12 -0600 Subject: [PATCH] Remove unused SVR3 controller and client --- service/config/sample-secrets-bundle.yml | 3 - service/config/sample.yml | 31 --- .../WhisperServerConfiguration.java | 8 - .../textsecuregcm/WhisperServerService.java | 15 +- .../RegistrationLockVerificationManager.java | 13 +- .../SecureValueRecovery3Configuration.java | 34 --- .../SecureValueRecovery3Controller.java | 161 -------------- .../entities/RegistrationLockFailure.java | 7 +- .../entities/SetShareSetRequest.java | 22 -- .../entities/Svr3Credentials.java | 28 --- .../SecureValueRecovery3Client.java | 86 -------- .../textsecuregcm/storage/Account.java | 21 -- .../textsecuregcm/storage/Accounts.java | 4 - .../storage/AccountsManager.java | 11 - .../workers/CommandDependencies.java | 10 +- ...gistrationLockVerificationManagerTest.java | 6 +- .../SecureValueRecovery3ControllerTest.java | 184 ---------------- ...SecureValueRecoveryControllerBaseTest.java | 1 - .../SecureValueRecovery3ClientTest.java | 196 ------------------ ...ccountCreationDeletionIntegrationTest.java | 5 - ...ntsManagerChangeNumberIntegrationTest.java | 5 - ...ConcurrentModificationIntegrationTest.java | 2 - ...sManagerDeviceTransferIntegrationTest.java | 3 +- .../storage/AccountsManagerTest.java | 19 -- ...ccountsManagerUsernameIntegrationTest.java | 2 - .../textsecuregcm/storage/AccountsTest.java | 2 - .../AddRemoveDeviceIntegrationTest.java | 5 - .../resources/config/test-secrets-bundle.yml | 3 - service/src/test/resources/config/test.yml | 31 --- 29 files changed, 13 insertions(+), 905 deletions(-) delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/configuration/SecureValueRecovery3Configuration.java delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery3Controller.java delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/entities/SetShareSetRequest.java delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/entities/Svr3Credentials.java delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery3Client.java delete mode 100644 service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery3ControllerTest.java delete mode 100644 service/src/test/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery3ClientTest.java diff --git a/service/config/sample-secrets-bundle.yml b/service/config/sample-secrets-bundle.yml index 636ad6e91..9c56b6857 100644 --- a/service/config/sample-secrets-bundle.yml +++ b/service/config/sample-secrets-bundle.yml @@ -16,9 +16,6 @@ directoryV2.client.userIdTokenSharedSecret: bbcdefghijklmnopqrstuvwxyz0123456789 svr2.userAuthenticationTokenSharedSecret: abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with SVR2 to generate auth tokens for Signal users svr2.userIdTokenSharedSecret: bbcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with SVR2 to generate auth identity tokens for Signal users -svr3.userAuthenticationTokenSharedSecret: cbcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with SVR3 to generate auth tokens for Signal users -svr3.userIdTokenSharedSecret: dbcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with SVR3 to generate auth identity tokens for Signal users - tus.userAuthenticationTokenSharedSecret: abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= gcpAttachments.rsaSigningKey: | diff --git a/service/config/sample.yml b/service/config/sample.yml index 00578b53e..1e4575d9b 100644 --- a/service/config/sample.yml +++ b/service/config/sample.yml @@ -219,37 +219,6 @@ svr2: AAAAAAAAAAAAAAAAAAAA -----END CERTIFICATE----- -svr3: - backend1Uri: backend1.example.com - backend2Uri: backend2.example.com - backend3Uri: backend3.example.com - userAuthenticationTokenSharedSecret: secret://svr3.userAuthenticationTokenSharedSecret - userIdTokenSharedSecret: secret://svr3.userIdTokenSharedSecret - svrCaCertificates: - - | - -----BEGIN CERTIFICATE----- - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz - AAAAAAAAAAAAAAAAAAAA - -----END CERTIFICATE----- - - messageCache: # Redis server configuration for message store cache persistDelayMinutes: 1 cluster: diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java index e173ae2d0..fb99adb77 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java @@ -52,7 +52,6 @@ import org.whispersystems.textsecuregcm.configuration.ReportMessageConfiguration import org.whispersystems.textsecuregcm.configuration.S3ObjectMonitorFactory; import org.whispersystems.textsecuregcm.configuration.SecureStorageServiceConfiguration; import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery2Configuration; -import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery3Configuration; import org.whispersystems.textsecuregcm.configuration.ShortCodeExpanderConfiguration; import org.whispersystems.textsecuregcm.configuration.SpamFilterConfiguration; import org.whispersystems.textsecuregcm.configuration.StripeConfiguration; @@ -157,10 +156,6 @@ public class WhisperServerConfiguration extends Configuration { @Valid @JsonProperty private SecureValueRecovery2Configuration svr2; - @NotNull - @Valid - @JsonProperty - private SecureValueRecovery3Configuration svr3; @NotNull @Valid @@ -410,9 +405,6 @@ public class WhisperServerConfiguration extends Configuration { public SecureValueRecovery2Configuration getSvr2Configuration() { return svr2; } - public SecureValueRecovery3Configuration getSvr3Configuration() { - return svr3; - } public DirectoryV2Configuration getDirectoryV2Configuration() { return directoryV2; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index aa5f5dc17..bb8fe712b 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -131,7 +131,6 @@ import org.whispersystems.textsecuregcm.controllers.RegistrationController; import org.whispersystems.textsecuregcm.controllers.RemoteConfigController; import org.whispersystems.textsecuregcm.controllers.SecureStorageController; import org.whispersystems.textsecuregcm.controllers.SecureValueRecovery2Controller; -import org.whispersystems.textsecuregcm.controllers.SecureValueRecovery3Controller; import org.whispersystems.textsecuregcm.controllers.StickerController; import org.whispersystems.textsecuregcm.controllers.SubscriptionController; import org.whispersystems.textsecuregcm.controllers.VerificationController; @@ -206,7 +205,6 @@ import org.whispersystems.textsecuregcm.s3.PolicySigner; import org.whispersystems.textsecuregcm.s3.PostPolicyGenerator; import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client; -import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery3Client; import org.whispersystems.textsecuregcm.spam.ChallengeConstraintChecker; import org.whispersystems.textsecuregcm.spam.RegistrationFraudChecker; import org.whispersystems.textsecuregcm.spam.RegistrationRecoveryChecker; @@ -481,8 +479,6 @@ public class WhisperServerService extends Application svrCaCertificates, - @NotNull @Valid CircuitBreakerConfiguration circuitBreaker, - @NotNull @Valid RetryConfiguration retry) { - - public SecureValueRecovery3Configuration { - if (circuitBreaker == null) { - circuitBreaker = new CircuitBreakerConfiguration(); - } - - if (retry == null) { - retry = new RetryConfiguration(); - } - } -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery3Controller.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery3Controller.java deleted file mode 100644 index 9eab281ab..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery3Controller.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2023 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.controllers; - -import com.google.common.annotations.VisibleForTesting; -import io.dropwizard.auth.Auth; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotNull; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.PUT; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import java.time.Clock; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import org.whispersystems.textsecuregcm.auth.AuthenticatedDevice; -import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials; -import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator; -import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsSelector; -import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery3Configuration; -import org.whispersystems.textsecuregcm.entities.AuthCheckRequest; -import org.whispersystems.textsecuregcm.entities.AuthCheckResponseV3; -import org.whispersystems.textsecuregcm.entities.SetShareSetRequest; -import org.whispersystems.textsecuregcm.entities.Svr3Credentials; -import org.whispersystems.textsecuregcm.limits.RateLimitedByIp; -import org.whispersystems.textsecuregcm.limits.RateLimiters; -import org.whispersystems.textsecuregcm.storage.Account; -import org.whispersystems.textsecuregcm.storage.AccountsManager; -import org.whispersystems.textsecuregcm.util.Optionals; -import org.whispersystems.websocket.auth.Mutable; -import org.whispersystems.websocket.auth.ReadOnly; - -@Path("/v3/backup") -@Tag(name = "Secure Value Recovery") -public class SecureValueRecovery3Controller { - - private static final long MAX_AGE_SECONDS = TimeUnit.DAYS.toSeconds(30); - - public static ExternalServiceCredentialsGenerator credentialsGenerator(final SecureValueRecovery3Configuration cfg) { - return credentialsGenerator(cfg, Clock.systemUTC()); - } - - @VisibleForTesting - public static ExternalServiceCredentialsGenerator credentialsGenerator(final SecureValueRecovery3Configuration cfg, - final Clock clock) { - return ExternalServiceCredentialsGenerator - .builder(cfg.userAuthenticationTokenSharedSecret()) - .withUserDerivationKey(cfg.userIdTokenSharedSecret().value()) - .prependUsername(false) - .withDerivedUsernameTruncateLength(16) - .withClock(clock) - .build(); - } - - private final ExternalServiceCredentialsGenerator backupServiceCredentialGenerator; - private final AccountsManager accountsManager; - - public SecureValueRecovery3Controller(final ExternalServiceCredentialsGenerator backupServiceCredentialGenerator, - final AccountsManager accountsManager) { - this.backupServiceCredentialGenerator = backupServiceCredentialGenerator; - this.accountsManager = accountsManager; - } - - @GET - @Path("/auth") - @Produces(MediaType.APPLICATION_JSON) - @Operation( - summary = "Generate credentials for SVR3", - description = """ - Generate SVR3 service credentials. Generated credentials have an expiration time of 30 days - (however, the TTL is fully controlled by the server side and may change even for already generated credentials). - - If a share-set has been previously set via /v3/backups/share-set, it will be included in the response - """) - @ApiResponse(responseCode = "200", description = "`JSON` with generated credentials and share-set", useReturnTypeSchema = true) - @ApiResponse(responseCode = "401", description = "Account authentication check failed.") - public Svr3Credentials getAuth(@ReadOnly @Auth final AuthenticatedDevice auth) { - final ExternalServiceCredentials creds = backupServiceCredentialGenerator.generateFor( - auth.getAccount().getUuid().toString()); - return new Svr3Credentials(creds.username(), creds.password(), auth.getAccount().getSvr3ShareSet()); - } - - @PUT - @Path("/share-set") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @Operation( - summary = "Set a share-set for the account", - description = """ - Add a share-set to the account that can later be retrieved at v3/backups/auth or during registration. After - storing a value with SVR3, clients must store the returned share-set so the value can be restored later. - """) - @ApiResponse(responseCode = "204", description = "Successfully set share-set") - @ApiResponse(responseCode = "401", description = "Account authentication check failed.") - public void setShareSet( - @Mutable @Auth final AuthenticatedDevice auth, - @NotNull @Valid final SetShareSetRequest request) { - accountsManager.update(auth.getAccount(), account -> account.setSvr3ShareSet(request.shareSet())); - } - - @POST - @Path("/auth/check") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @RateLimitedByIp(RateLimiters.For.BACKUP_AUTH_CHECK) - @Operation( - summary = "Check SVR3 credentials", - description = """ - Over time, clients may wind up with multiple sets of SVR3 authentication credentials in cloud storage. - To determine which set is most current and should be used to communicate with SVR3 to retrieve a master key - (from which a registration recovery password can be derived), clients should call this endpoint - with a list of stored credentials. The response will identify which (if any) set of credentials are - appropriate for communicating with SVR3. - """) - @ApiResponse(responseCode = "200", description = "`JSON` with the check results.", useReturnTypeSchema = true) - @ApiResponse(responseCode = "422", description = "Provided list of SVR3 credentials could not be parsed") - @ApiResponse(responseCode = "400", description = "`POST` request body is not a valid `JSON`") - public AuthCheckResponseV3 authCheck(@NotNull @Valid final AuthCheckRequest request) { - final List credentials = ExternalServiceCredentialsSelector.check( - request.tokens(), - backupServiceCredentialGenerator, - MAX_AGE_SECONDS); - - final Optional account = accountsManager.getByE164(request.number()); - - // the username associated with the provided number - final Optional matchingUsername = account - .map(Account::getUuid) - .map(backupServiceCredentialGenerator::generateForUuid) - .map(ExternalServiceCredentials::username); - - return new AuthCheckResponseV3(credentials.stream().collect(Collectors.toMap( - ExternalServiceCredentialsSelector.CredentialInfo::token, - info -> { - if (!info.valid()) { - // This isn't a valid credential (could be for a different SVR service, expired, etc) - return AuthCheckResponseV3.Result.invalid(); - } - final String credUsername = info.credentials().username(); - - return Optionals - // If the account exists, and the account's username matches this credential's username, return a match - .zipWith(account, matchingUsername.filter(credUsername::equals), (a, ignored) -> - AuthCheckResponseV3.Result.match(a.getSvr3ShareSet())) - // Otherwise, return no-match - .orElseGet(AuthCheckResponseV3.Result::noMatch); - } - ))); - } -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/entities/RegistrationLockFailure.java b/service/src/main/java/org/whispersystems/textsecuregcm/entities/RegistrationLockFailure.java index 5bdfa2980..80b51202e 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/entities/RegistrationLockFailure.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/entities/RegistrationLockFailure.java @@ -6,6 +6,7 @@ package org.whispersystems.textsecuregcm.entities; import io.swagger.v3.oas.annotations.media.Schema; +import javax.annotation.Nullable; import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials; @Schema(description = """ @@ -16,7 +17,9 @@ public record RegistrationLockFailure( @Schema(description = "Time remaining in milliseconds before the existing registration lock expires") long timeRemaining, @Schema(description = "Credentials that can be used with SVR2") + @Nullable ExternalServiceCredentials svr2Credentials, - @Schema(description = "Credentials that can be used with SVR3") - Svr3Credentials svr3Credentials) { + @Deprecated + @Nullable + ExternalServiceCredentials svr3Credentials) { } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/entities/SetShareSetRequest.java b/service/src/main/java/org/whispersystems/textsecuregcm/entities/SetShareSetRequest.java deleted file mode 100644 index 122564334..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/entities/SetShareSetRequest.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2024 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ -package org.whispersystems.textsecuregcm.entities; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import org.whispersystems.textsecuregcm.util.ByteArrayAdapter; -import org.whispersystems.textsecuregcm.util.ExactlySize; - -public record SetShareSetRequest( - @Schema(description = """ - A share-set generated by a client after storing a value in SVR3, serialized in un-padded standard base64 - """, implementation = String.class) - @JsonDeserialize(using = ByteArrayAdapter.Deserializing.class) - @NotEmpty - @ExactlySize(SHARE_SET_SIZE) - byte[] shareSet) { - public static final int SHARE_SET_SIZE = 169; -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/entities/Svr3Credentials.java b/service/src/main/java/org/whispersystems/textsecuregcm/entities/Svr3Credentials.java deleted file mode 100644 index 888cec857..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/entities/Svr3Credentials.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2024 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ -package org.whispersystems.textsecuregcm.entities; - -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import io.swagger.v3.oas.annotations.media.Schema; -import javax.annotation.Nullable; -import org.whispersystems.textsecuregcm.util.ByteArrayAdapter; - -@Schema(description = """ - A time limited external service credential that can be used to authenticate and restore from SVR3. - """) -public record Svr3Credentials( - - @Schema(description = "The credential username") - String username, - - @Schema(description = "The credential password") - String password, - - @Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED, description = """ - If present, a shareSet previously stored for this account via /v3/backups/shareSet. Required to restore a value - from SVR3. Encoded in standard un-padded base64. - """, implementation = String.class) - @JsonSerialize(using = ByteArrayAdapter.Serializing.class) - @Nullable byte[] shareSet) {} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery3Client.java b/service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery3Client.java deleted file mode 100644 index 33ae74c48..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery3Client.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2024 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.securevaluerecovery; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.net.HttpHeaders; -import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials; -import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator; -import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery3Configuration; -import org.whispersystems.textsecuregcm.http.FaultTolerantHttpClient; -import org.whispersystems.textsecuregcm.util.ExceptionUtils; -import org.whispersystems.textsecuregcm.util.HttpUtils; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.security.cert.CertificateException; -import java.time.Duration; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledExecutorService; -import java.util.stream.Stream; - -import static org.whispersystems.textsecuregcm.util.HeaderUtils.basicAuthHeader; - -/** - * A client for sending requests to Signal's secure value recovery v3 service on behalf of authenticated users. - */ -public class SecureValueRecovery3Client { - private final ExternalServiceCredentialsGenerator secureValueRecoveryCredentialsGenerator; - private final URI backend1Uri; - private final URI backend2Uri; - private final URI backend3Uri; - - private final FaultTolerantHttpClient httpClient; - - @VisibleForTesting - static final String DELETE_PATH = "/v1/delete"; - - public SecureValueRecovery3Client(final ExternalServiceCredentialsGenerator secureValueRecoveryCredentialsGenerator, - final Executor executor, final ScheduledExecutorService retryExecutor, - final SecureValueRecovery3Configuration configuration) - throws CertificateException { - this.secureValueRecoveryCredentialsGenerator = secureValueRecoveryCredentialsGenerator; - this.backend1Uri = URI.create(configuration.backend1Uri()).resolve(DELETE_PATH); - this.backend2Uri = URI.create(configuration.backend2Uri()).resolve(DELETE_PATH); - this.backend3Uri = URI.create(configuration.backend3Uri()).resolve(DELETE_PATH); - this.httpClient = FaultTolerantHttpClient.newBuilder() - .withCircuitBreaker(configuration.circuitBreaker()) - .withRetry(configuration.retry()) - .withRetryExecutor(retryExecutor) - .withVersion(HttpClient.Version.HTTP_1_1) - .withConnectTimeout(Duration.ofSeconds(10)) - .withRedirect(HttpClient.Redirect.NEVER) - .withExecutor(executor) - .withName("secure-value-recovery3") - .withSecurityProtocol(FaultTolerantHttpClient.SECURITY_PROTOCOL_TLS_1_2) - .withTrustedServerCertificates(configuration.svrCaCertificates().toArray(String[]::new)) - .build(); - } - - public CompletableFuture deleteBackups(final UUID accountUuid) { - final ExternalServiceCredentials credentials = secureValueRecoveryCredentialsGenerator.generateForUuid(accountUuid); - final List>> futures = Stream.of(backend1Uri, backend2Uri, backend3Uri) - .map(uri -> HttpRequest.newBuilder() - .uri(uri) - .DELETE() - .header(HttpHeaders.AUTHORIZATION, basicAuthHeader(credentials)) - .build()) - .map(request -> httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())) - .toList(); - - return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)) - .thenApply(ignored -> futures.stream().map(CompletableFuture::join).toList()) - .thenAccept(responses -> responses.forEach(response -> { - if (!HttpUtils.isSuccessfulResponse(response.statusCode())) { - throw new SecureValueRecoveryException(String.format("Failed to delete backup in %s", response.uri()), String.valueOf(response.statusCode())); - } - })); - } -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java index 6111e0e53..2535c4825 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java @@ -100,19 +100,6 @@ public class Account { @JsonProperty("inCds") private boolean discoverableByPhoneNumber = true; - /** - * A share-set the account holder has stored. - * - * A share-set is generated when a client stores a value in SVR3, and should be stored here with the account. When - * they later want to recover the value, they need their share-set and their secret pin. The share-set is not a secret - * and, without the correct pin, is useless information. - * - * SVR3 share-sets are currently 167 bytes. - */ - @JsonProperty("svr3ss") - @Nullable - private byte[] svr3ShareSet; - @JsonProperty("bcr") @Nullable private byte[] messagesBackupCredentialRequest; @@ -485,14 +472,6 @@ public class Account { this.version = version; } - public @Nullable byte[] getSvr3ShareSet() { - return svr3ShareSet; - } - - public void setSvr3ShareSet(final byte[] svr3ShareSet) { - this.svr3ShareSet = svr3ShareSet; - } - public void setBackupCredentialRequests(final byte[] messagesBackupCredentialRequest, final byte[] mediaBackupCredentialRequest) { diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java index 9016458e6..c55eb8594 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java @@ -315,10 +315,6 @@ public class Accounts { existingAccount.getBackupCredentialRequest(BackupCredentialType.MESSAGES).orElse(null), existingAccount.getBackupCredentialRequest(BackupCredentialType.MEDIA).orElse(null)); - // Carry over the old SVR3 share-set. This is required for an account to restore information from SVR. The share- - // set is not a secret, if the new account claimer does not have the SVR3 pin, it is useless. - accountToCreate.setSvr3ShareSet(existingAccount.getSvr3ShareSet()); - final List writeItems = new ArrayList<>(); // If we're reclaiming an account that already has a username, we'd like to give the re-registering client diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java index 5044fe80b..7fd6274d1 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java @@ -82,7 +82,6 @@ import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClient; import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClusterClient; import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client; -import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery3Client; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecoveryException; import org.whispersystems.textsecuregcm.util.DestinationDeviceValidator; import org.whispersystems.textsecuregcm.util.ExceptionUtils; @@ -126,7 +125,6 @@ public class AccountsManager extends RedisPubSubAdapter implemen private final ProfilesManager profilesManager; private final SecureStorageClient secureStorageClient; private final SecureValueRecovery2Client secureValueRecovery2Client; - private final SecureValueRecovery3Client secureValueRecovery3Client; private final DisconnectionRequestManager disconnectionRequestManager; private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager; @@ -210,7 +208,6 @@ public class AccountsManager extends RedisPubSubAdapter implemen final ProfilesManager profilesManager, final SecureStorageClient secureStorageClient, final SecureValueRecovery2Client secureValueRecovery2Client, - final SecureValueRecovery3Client secureValueRecovery3Client, final DisconnectionRequestManager disconnectionRequestManager, final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager, final ClientPublicKeysManager clientPublicKeysManager, @@ -229,7 +226,6 @@ public class AccountsManager extends RedisPubSubAdapter implemen this.profilesManager = profilesManager; this.secureStorageClient = secureStorageClient; this.secureValueRecovery2Client = secureValueRecovery2Client; - this.secureValueRecovery3Client = secureValueRecovery3Client; this.disconnectionRequestManager = disconnectionRequestManager; this.registrationRecoveryPasswordsManager = requireNonNull(registrationRecoveryPasswordsManager); this.clientPublicKeysManager = clientPublicKeysManager; @@ -1264,16 +1260,9 @@ public class AccountsManager extends RedisPubSubAdapter implemen throw new CompletionException(exception); })); - final CompletableFuture svr3DeleteBackupFuture = secureValueRecovery3Client.deleteBackups(account.getUuid()) - .exceptionally(exception -> { - // We don't care about errors from SVR3 because we're not currently using it - return null; - }); - return CompletableFuture.allOf( secureStorageClient.deleteStoredData(account.getUuid()), svr2DeleteBackupFuture, - svr3DeleteBackupFuture, keysManager.deleteSingleUsePreKeys(account.getUuid()), keysManager.deleteSingleUsePreKeys(account.getPhoneNumberIdentifier()), messagesManager.clear(account.getUuid()), diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/CommandDependencies.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/CommandDependencies.java index 34657f680..b25f8abe1 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/CommandDependencies.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/CommandDependencies.java @@ -32,7 +32,6 @@ import org.whispersystems.textsecuregcm.backup.Cdn3RemoteStorageManager; import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration; import org.whispersystems.textsecuregcm.controllers.SecureStorageController; import org.whispersystems.textsecuregcm.controllers.SecureValueRecovery2Controller; -import org.whispersystems.textsecuregcm.controllers.SecureValueRecovery3Controller; import org.whispersystems.textsecuregcm.experiment.PushNotificationExperimentSamples; import org.whispersystems.textsecuregcm.limits.RateLimiters; import org.whispersystems.textsecuregcm.metrics.MicrometerAwsSdkMetricPublisher; @@ -45,7 +44,6 @@ import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClient; import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClusterClient; import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client; -import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery3Client; import org.whispersystems.textsecuregcm.storage.AccountLockManager; import org.whispersystems.textsecuregcm.storage.Accounts; import org.whispersystems.textsecuregcm.storage.AccountsManager; @@ -161,8 +159,6 @@ record CommandDependencies( configuration.getSecureStorageServiceConfiguration()); ExternalServiceCredentialsGenerator secureValueRecovery2CredentialsGenerator = SecureValueRecovery2Controller.credentialsGenerator( configuration.getSvr2Configuration()); - ExternalServiceCredentialsGenerator secureValueRecovery3CredentialsGenerator = SecureValueRecovery3Controller.credentialsGenerator( - configuration.getSvr3Configuration()); final ExecutorService awsSdkMetricsExecutor = environment.lifecycle() .virtualExecutorService(MetricRegistry.name(CommandDependencies.class, "awsSdkMetrics-%d")); @@ -215,10 +211,6 @@ record CommandDependencies( secureValueRecovery2CredentialsGenerator, secureValueRecoveryServiceExecutor, secureValueRecoveryServiceRetryExecutor, configuration.getSvr2Configuration()); - SecureValueRecovery3Client secureValueRecovery3Client = new SecureValueRecovery3Client( - secureValueRecovery3CredentialsGenerator, secureValueRecoveryServiceExecutor, - secureValueRecoveryServiceRetryExecutor, - configuration.getSvr3Configuration()); SecureStorageClient secureStorageClient = new SecureStorageClient(storageCredentialsGenerator, storageServiceExecutor, storageServiceRetryExecutor, configuration.getSecureStorageServiceConfiguration()); DisconnectionRequestManager disconnectionRequestManager = new DisconnectionRequestManager(pubsubClient, disconnectionRequestListenerExecutor); @@ -240,7 +232,7 @@ record CommandDependencies( new RegistrationRecoveryPasswordsManager(registrationRecoveryPasswords); AccountsManager accountsManager = new AccountsManager(accounts, phoneNumberIdentifiers, cacheCluster, pubsubClient, accountLockManager, keys, messagesManager, profilesManager, - secureStorageClient, secureValueRecovery2Client, secureValueRecovery3Client, disconnectionRequestManager, + secureStorageClient, secureValueRecovery2Client, disconnectionRequestManager, registrationRecoveryPasswordsManager, clientPublicKeysManager, accountLockExecutor, messagePollExecutor, clock, configuration.getLinkDeviceSecretConfiguration().secret().value(), dynamicConfigurationManager); RateLimiters rateLimiters = RateLimiters.createAndValidate(configuration.getLimitsConfiguration(), diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManagerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManagerTest.java index a9ff62c6d..3171e43ba 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManagerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManagerTest.java @@ -49,15 +49,13 @@ class RegistrationLockVerificationManagerTest { private final DisconnectionRequestManager disconnectionRequestManager = mock(DisconnectionRequestManager.class); private final ExternalServiceCredentialsGenerator svr2CredentialsGenerator = mock( ExternalServiceCredentialsGenerator.class); - private final ExternalServiceCredentialsGenerator svr3CredentialsGenerator = mock( - ExternalServiceCredentialsGenerator.class); private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager = mock( RegistrationRecoveryPasswordsManager.class); private final PushNotificationManager pushNotificationManager = mock(PushNotificationManager.class); private final RateLimiters rateLimiters = mock(RateLimiters.class); private final RegistrationLockVerificationManager registrationLockVerificationManager = new RegistrationLockVerificationManager( - accountsManager, disconnectionRequestManager, svr2CredentialsGenerator, - svr3CredentialsGenerator, registrationRecoveryPasswordsManager, pushNotificationManager, rateLimiters); + accountsManager, disconnectionRequestManager, svr2CredentialsGenerator, registrationRecoveryPasswordsManager, + pushNotificationManager, rateLimiters); private final RateLimiter pinLimiter = mock(RateLimiter.class); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery3ControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery3ControllerTest.java deleted file mode 100644 index 6783cd9c2..000000000 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery3ControllerTest.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2023 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.controllers; - - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.whispersystems.textsecuregcm.util.MockUtils.randomSecretBytes; - -import io.dropwizard.auth.AuthValueFactoryProvider; -import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; -import io.dropwizard.testing.junit5.ResourceExtension; -import jakarta.ws.rs.client.Entity; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import java.util.Base64; -import java.util.Collections; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import javax.annotation.Nullable; -import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.whispersystems.textsecuregcm.auth.AuthenticatedDevice; -import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator; -import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery3Configuration; -import org.whispersystems.textsecuregcm.entities.AuthCheckRequest; -import org.whispersystems.textsecuregcm.entities.AuthCheckResponseV3; -import org.whispersystems.textsecuregcm.entities.SetShareSetRequest; -import org.whispersystems.textsecuregcm.storage.Account; -import org.whispersystems.textsecuregcm.storage.AccountsManager; -import org.whispersystems.textsecuregcm.tests.util.AuthHelper; -import org.whispersystems.textsecuregcm.util.MutableClock; -import org.whispersystems.textsecuregcm.util.SystemMapper; -import org.whispersystems.textsecuregcm.util.TestRandomUtil; - -@ExtendWith(DropwizardExtensionsSupport.class) -public class SecureValueRecovery3ControllerTest extends SecureValueRecoveryControllerBaseTest { - - private static final SecureValueRecovery3Configuration CFG = new SecureValueRecovery3Configuration( - "", - "", - "", - randomSecretBytes(32), - randomSecretBytes(32), - null, - null, - null - ); - - private static final MutableClock CLOCK = new MutableClock(); - - private static final ExternalServiceCredentialsGenerator CREDENTIAL_GENERATOR = - SecureValueRecovery3Controller.credentialsGenerator(CFG, CLOCK); - - private static final AccountsManager ACCOUNTS_MANAGER = mock(AccountsManager.class); - private static final SecureValueRecovery3Controller CONTROLLER = - new SecureValueRecovery3Controller(CREDENTIAL_GENERATOR, ACCOUNTS_MANAGER); - - private static final ResourceExtension RESOURCES = ResourceExtension.builder() - .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedDevice.class)) - .setMapper(SystemMapper.jsonMapper()) - .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) - .addResource(CONTROLLER) - .build(); - - protected SecureValueRecovery3ControllerTest() { - super("/v3", ACCOUNTS_MANAGER, CLOCK, RESOURCES, CREDENTIAL_GENERATOR); - } - - @Override - Map parseCheckResponse(final Response response) { - final AuthCheckResponseV3 authCheckResponse = response.readEntity(AuthCheckResponseV3.class); - - assertFalse(authCheckResponse.matches() - .values().stream() - .anyMatch(r -> r.status() == AuthCheckResponseV3.CredentialStatus.MATCH && r.shareSet() == null), - "SVR3 matches must contain a non-empty share-set"); - - return authCheckResponse.matches().entrySet().stream().collect(Collectors.toMap( - Map.Entry::getKey, e -> switch (e.getValue().status()) { - case MATCH -> CheckStatus.MATCH; - case INVALID -> CheckStatus.INVALID; - case NO_MATCH -> CheckStatus.NO_MATCH; - } - )); - } - - - public static Stream checkShareSet() { - byte[] shareSet = TestRandomUtil.nextBytes(100); - return Stream.of( - Arguments.of(shareSet, AuthCheckResponseV3.Result.match(shareSet)), - Arguments.of(null, AuthCheckResponseV3.Result.match(null))); - } - - @ParameterizedTest - @MethodSource - public void checkShareSet(@Nullable byte[] shareSet, AuthCheckResponseV3.Result expectedResult) { - final String e164 = "+18005550101"; - final UUID uuid = UUID.randomUUID(); - final String token = token(uuid, day(10)); - CLOCK.setTimeMillis(day(11)); - - final Account a = mock(Account.class); - when(a.getUuid()).thenReturn(uuid); - when(a.getSvr3ShareSet()).thenReturn(shareSet); - when(ACCOUNTS_MANAGER.getByE164(e164)).thenReturn(Optional.of(a)); - - final AuthCheckRequest in = new AuthCheckRequest(e164, Collections.singletonList(token)); - final Response response = RESOURCES.getJerseyTest() - .target("/v3/backup/auth/check") - .request() - .post(Entity.entity(in, MediaType.APPLICATION_JSON)); - - try (response) { - assertEquals(200, response.getStatus()); - AuthCheckResponseV3 checkResponse = response.readEntity(AuthCheckResponseV3.class); - assertEquals(checkResponse.matches().size(), 1); - assertEquals(checkResponse.matches().get(token).status(), expectedResult.status()); - assertArrayEquals(checkResponse.matches().get(token).shareSet(), expectedResult.shareSet()); - } - } - - @Test - public void setShareSet() { - final Account a = mock(Account.class); - when(ACCOUNTS_MANAGER.update(any(), any())).thenAnswer(invocation -> { - final Consumer updater = invocation.getArgument(1); - updater.accept(a); - return null; - }); - - byte[] shareSet = TestRandomUtil.nextBytes(SetShareSetRequest.SHARE_SET_SIZE); - final Response response = RESOURCES.getJerseyTest() - .target("/v3/backup/share-set") - .request() - .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) - .put(Entity.entity(new SetShareSetRequest(shareSet), MediaType.APPLICATION_JSON)); - - assertEquals(204, response.getStatus()); - verify(a, times(1)).setSvr3ShareSet(eq(shareSet)); - } - - static Stream requestParsing() { - return Stream.of( - Arguments.of("", 422), - Arguments.of(null, 422), - Arguments.of("abc**", 400), // bad base64 - Arguments.of(Base64.getEncoder().encodeToString(TestRandomUtil.nextBytes(SetShareSetRequest.SHARE_SET_SIZE - 1)), 422), - Arguments.of(Base64.getEncoder().encodeToString(TestRandomUtil.nextBytes(SetShareSetRequest.SHARE_SET_SIZE)), 204)); - } - - @ParameterizedTest - @MethodSource - public void requestParsing(String shareSet, int responseCode) { - final Response response = RESOURCES.getJerseyTest() - .target("/v3/backup/share-set") - .request() - .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) - .put(Entity.entity(""" - {"shareSet": "%s"} - """.formatted(shareSet), MediaType.APPLICATION_JSON)); - assertEquals(responseCode, response.getStatus()); - } -} diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecoveryControllerBaseTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecoveryControllerBaseTest.java index 3a6e6cfed..e67079c29 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecoveryControllerBaseTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecoveryControllerBaseTest.java @@ -319,7 +319,6 @@ abstract class SecureValueRecoveryControllerBaseTest { private static Account account(final UUID uuid) { final Account a = new Account(); a.setUuid(uuid); - a.setSvr3ShareSet(TestRandomUtil.nextBytes(100)); return a; } } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery3ClientTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery3ClientTest.java deleted file mode 100644 index 19b7dde07..000000000 --- a/service/src/test/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery3ClientTest.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2024 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.securevaluerecovery; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.delete; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.whispersystems.textsecuregcm.util.MockUtils.randomSecretBytes; - -import com.github.tomakehurst.wiremock.junit5.WireMockExtension; -import java.security.cert.CertificateException; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.CompletionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; -import org.apache.commons.lang3.RandomStringUtils; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials; -import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator; -import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery3Configuration; - -class SecureValueRecovery3ClientTest { - - private UUID accountUuid; - private ExternalServiceCredentialsGenerator credentialsGenerator; - private ExecutorService httpExecutor; - private ScheduledExecutorService retryExecutor; - - private SecureValueRecovery3Client secureValueRecovery3Client; - - @RegisterExtension - private static final WireMockExtension backend1WireMock = WireMockExtension.newInstance() - .options(wireMockConfig().dynamicPort().dynamicHttpsPort()) - .build(); - - @RegisterExtension - private static final WireMockExtension backend2WireMock = WireMockExtension.newInstance() - .options(wireMockConfig().dynamicPort().dynamicHttpsPort()) - .build(); - - @RegisterExtension - private static final WireMockExtension backend3WireMock = WireMockExtension.newInstance() - .options(wireMockConfig().dynamicPort().dynamicHttpsPort()) - .build(); - - @BeforeEach - void setUp() throws CertificateException { - accountUuid = UUID.randomUUID(); - credentialsGenerator = mock(ExternalServiceCredentialsGenerator.class); - httpExecutor = Executors.newSingleThreadExecutor(); - retryExecutor = Executors.newSingleThreadScheduledExecutor(); - - final SecureValueRecovery3Configuration config = new SecureValueRecovery3Configuration( - "http://localhost:" + backend1WireMock.getPort(), - "http://localhost:" + backend2WireMock.getPort(), - "http://localhost:" + backend3WireMock.getPort(), - randomSecretBytes(32), - randomSecretBytes(32), - // This is a randomly-generated, throwaway certificate that's not actually connected to anything - List.of(""" - -----BEGIN CERTIFICATE----- - MIICZDCCAc2gAwIBAgIBADANBgkqhkiG9w0BAQ0FADBPMQswCQYDVQQGEwJ1czEL - MAkGA1UECAwCVVMxHjAcBgNVBAoMFVNpZ25hbCBNZXNzZW5nZXIsIExMQzETMBEG - A1UEAwwKc2lnbmFsLm9yZzAeFw0yMDEyMjMyMjQ3NTlaFw0zMDEyMjEyMjQ3NTla - ME8xCzAJBgNVBAYTAnVzMQswCQYDVQQIDAJVUzEeMBwGA1UECgwVU2lnbmFsIE1l - c3NlbmdlciwgTExDMRMwEQYDVQQDDApzaWduYWwub3JnMIGfMA0GCSqGSIb3DQEB - AQUAA4GNADCBiQKBgQCfSLcZNHYqbxSsgWp4JvbPRHjQTrlsrKrgD2q7f/OY6O3Y - /X0QNcNSOJpliN8rmzwslfsrXHO3q1diGRw4xHogUJZ/7NQrHiP/zhN0VTDh49pD - ZpjXVyUbayLS/6qM5arKxBspzEFBb5v8cF6bPr76SO/rpGXiI0j6yJKX6fRiKwID - AQABo1AwTjAdBgNVHQ4EFgQU6Jrs/Fmj0z4dA3wvdq/WqA4P49IwHwYDVR0jBBgw - FoAU6Jrs/Fmj0z4dA3wvdq/WqA4P49IwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B - AQ0FAAOBgQB+5d5+NtzLILfrc9QmJdIO1YeDP64JmFwTER0kEUouRsb9UwknVWZa - y7MTM4NoBV1k0zb5LAk89SIDPr/maW5AsLtEomzjnEiomjoMBUdNe3YCgQReoLnr - R/QaUNbrCjTGYfBsjGbIzmkWPUyTec2ZdRyJ8JiVl386+6CZkxnndQ== - -----END CERTIFICATE----- - """, """ - -----BEGIN CERTIFICATE----- - MIIEpDCCAowCCQC43PUTWSADVjANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAls - b2NhbGhvc3QwHhcNMjIxMDE3MjA0NTM0WhcNMjMxMDE3MjA0NTM0WjAUMRIwEAYD - VQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDV - x1cdEd2ffQTlTXWRiCHGcrlYf4RJnctt9sw/BuHWTLXBu5LhyJSGn5LRszO/NCXK - Z/cmGR7pLj366RtiwL+Qo3nhvDCK7T9xZeNIusM6XMcMK9D/DGCYPqtjQz8NXd9V - ajBBe6nwTDTa+oqX8Mt89foWNkg5Il/lY62u9Dr18LRZ2W9zzYi3Q9/K0CbIX6pM - yVlPIO5rITOR2IsbeyqsO9jufgX5lP4ZKLLBAP1b7usjC4YdvWacjQg/rK5aay1x - jC2HCDgo/4N30QVXzSA9nFfSe6AE/xkStK4819JqOkY5JsJCbef1P3hOOdSLEjbp - xq3MjOs6G6dOgteaAGs10vx7dHxDWETTIiD7BIZ9zRYgOF5bkCaIUO+JfySE1MHD - KBAFLoRuvmRev5Ln5R0MCHpUMSmMNgJqz+RWZV3g/gpYbuWiHgJOwL1393eK50Bg - W7SXQ8EjJj2yXZSH+1gPzN0DRoJZiaBoTPnCL2qUgvwFpW1PJsM5FDyUJFUoK5kK - HLBBSKAPt6ZlSrUe2nBgJv7EF1GK+fTU08LXgW33OpLceGPa0zTShkukQUMtUtZ8 - GqhO12ohMzEupIu5Xurthq4VVUrzHUdj1ZZRMhAbfLU36sd03MMyL/xBqTN6dzCa - GDGIPGpYjAllZ5xMRt2kZdv+Kr6oo3u2nLUIsqI7KQIDAQABMA0GCSqGSIb3DQEB - CwUAA4ICAQCB5s43YF35ssf5YONW5iAaifGpi1o0866xfeOybtohFGvQ7V2W34i9 - TYBCt8+0hgatMcvZ08f0vqig1i7nrvYcE1hnhL7JNkU8qm0s9ytHZt6j62nB0kd/ - uqE2hOEQalTf/2TGPV0CCgiqLyd8lEUQvQeA38wktwUeZpVnErlzHeMR2CvV3K8R - u4vV6SnBcf+TAt56RKYZkPyvZj5llQPo14Glyoo8qZES7Ky1SHmM0GL+baPRBjRW - 3KgSt98Wyu4yr9qu21JpnbAnLhBfzfSKjSeCRgFElUE1GIaFGRZ7ypA74dUKeLnb - /VUWrszmUhGaEjV9dpI6x6B/kSpQMtIQqBaKRY2ALUeEujS/rURi4iMDwSU+GkSH - cyEvZKS97OA/dWeXfLXdo4beDBRG93bI4rQnDg5+VdlBOkQSLueb8x6/VThMoC5d - vZiotFQHseljQAdTkNa6tBu6c4XDYPCKB3CfkMYOlCfTS7Acn5G6dxTPKBtLGBnL - nQfYyzuwYkN09+2PVzt6auBHr3To7uoclkxX+hxyvPIwIZ0N6b4tQR1FCAkvg29Q - WIOjZOKGW690ESKCKOnFjUHVO0HpuWnT81URTuY62FXsYdVc2wE4v0E04mEbqQ0P - lY6ZKNA81Lm3YADYtObmK1IUrOPo9BeIaPy0UM08SmN880Vunqa91Q== - -----END CERTIFICATE----- - """), - null, null); - - secureValueRecovery3Client = new SecureValueRecovery3Client(credentialsGenerator, httpExecutor, retryExecutor, - config); - } - - @AfterEach - void tearDown() throws InterruptedException { - httpExecutor.shutdown(); - httpExecutor.awaitTermination(1, TimeUnit.SECONDS); - retryExecutor.shutdown(); - retryExecutor.awaitTermination(1, TimeUnit.SECONDS); - } - - @Test - void deleteStoredData() { - final String username = RandomStringUtils.secure().nextAlphabetic(16); - final String password = RandomStringUtils.secure().nextAlphanumeric(32); - - when(credentialsGenerator.generateForUuid(accountUuid)).thenReturn( - new ExternalServiceCredentials(username, password)); - - backend1WireMock.stubFor(delete(urlEqualTo(SecureValueRecovery3Client.DELETE_PATH)) - .withBasicAuth(username, password) - .willReturn(aResponse().withStatus(202))); - - backend2WireMock.stubFor(delete(urlEqualTo(SecureValueRecovery3Client.DELETE_PATH)) - .withBasicAuth(username, password) - .willReturn(aResponse().withStatus(202))); - - backend3WireMock.stubFor(delete(urlEqualTo(SecureValueRecovery3Client.DELETE_PATH)) - .withBasicAuth(username, password) - .willReturn(aResponse().withStatus(202))); - - assertDoesNotThrow(() -> secureValueRecovery3Client.deleteBackups(accountUuid).join()); - } - - @ParameterizedTest - @MethodSource - void deleteStoredDataFailure(final int backend1Status, final int backend2Status, final int backend3Status) { - final String username = RandomStringUtils.secure().nextAlphabetic(16); - final String password = RandomStringUtils.secure().nextAlphanumeric(32); - - when(credentialsGenerator.generateForUuid(accountUuid)).thenReturn( - new ExternalServiceCredentials(username, password)); - - backend1WireMock.stubFor(delete(urlEqualTo(SecureValueRecovery3Client.DELETE_PATH)) - .withBasicAuth(username, password) - .willReturn(aResponse().withStatus(backend1Status))); - - backend2WireMock.stubFor(delete(urlEqualTo(SecureValueRecovery3Client.DELETE_PATH)) - .withBasicAuth(username, password) - .willReturn(aResponse().withStatus(backend2Status))); - - backend3WireMock.stubFor(delete(urlEqualTo(SecureValueRecovery3Client.DELETE_PATH)) - .withBasicAuth(username, password) - .willReturn(aResponse().withStatus(backend3Status))); - - final CompletionException completionException = assertThrows(CompletionException.class, - () -> secureValueRecovery3Client.deleteBackups(accountUuid).join()); - - assertInstanceOf(SecureValueRecoveryException.class, completionException.getCause()); - } - - private static Stream deleteStoredDataFailure() { - return Stream.of( - Arguments.of(400, 202, 202), - Arguments.of(202, 400, 202), - Arguments.of(202, 202, 400) - ); - } - -} diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountCreationDeletionIntegrationTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountCreationDeletionIntegrationTest.java index 74de894a0..57ca4652a 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountCreationDeletionIntegrationTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountCreationDeletionIntegrationTest.java @@ -49,7 +49,6 @@ import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClient; import org.whispersystems.textsecuregcm.redis.RedisClusterExtension; import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client; -import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery3Client; import org.whispersystems.textsecuregcm.tests.util.KeysHelper; public class AccountCreationDeletionIntegrationTest { @@ -126,9 +125,6 @@ public class AccountCreationDeletionIntegrationTest { final SecureValueRecovery2Client svr2Client = mock(SecureValueRecovery2Client.class); when(svr2Client.deleteBackups(any())).thenReturn(CompletableFuture.completedFuture(null)); - final SecureValueRecovery3Client svr3Client = mock(SecureValueRecovery3Client.class); - when(svr3Client.deleteBackups(any())).thenReturn(CompletableFuture.completedFuture(null)); - final PhoneNumberIdentifiers phoneNumberIdentifiers = new PhoneNumberIdentifiers(DYNAMO_DB_EXTENSION.getDynamoDbAsyncClient(), DynamoDbExtensionSchema.Tables.PNI.tableName()); @@ -159,7 +155,6 @@ public class AccountCreationDeletionIntegrationTest { profilesManager, secureStorageClient, svr2Client, - svr3Client, disconnectionRequestManager, registrationRecoveryPasswordsManager, clientPublicKeysManager, diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerChangeNumberIntegrationTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerChangeNumberIntegrationTest.java index dd8555631..20206f18c 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerChangeNumberIntegrationTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerChangeNumberIntegrationTest.java @@ -41,7 +41,6 @@ import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClient; import org.whispersystems.textsecuregcm.redis.RedisClusterExtension; import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client; -import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery3Client; import org.whispersystems.textsecuregcm.storage.DynamoDbExtensionSchema.Tables; import org.whispersystems.textsecuregcm.tests.util.AccountsHelper; import org.whispersystems.textsecuregcm.tests.util.KeysHelper; @@ -118,9 +117,6 @@ class AccountsManagerChangeNumberIntegrationTest { final SecureValueRecovery2Client svr2Client = mock(SecureValueRecovery2Client.class); when(svr2Client.deleteBackups(any())).thenReturn(CompletableFuture.completedFuture(null)); - final SecureValueRecovery3Client svr3Client = mock(SecureValueRecovery3Client.class); - when(svr3Client.deleteBackups(any())).thenReturn(CompletableFuture.completedFuture(null)); - disconnectionRequestManager = mock(DisconnectionRequestManager.class); final PhoneNumberIdentifiers phoneNumberIdentifiers = @@ -149,7 +145,6 @@ class AccountsManagerChangeNumberIntegrationTest { profilesManager, secureStorageClient, svr2Client, - svr3Client, disconnectionRequestManager, registrationRecoveryPasswordsManager, clientPublicKeysManager, diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java index 92127c526..b363cdd38 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java @@ -54,7 +54,6 @@ import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClient; import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client; -import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery3Client; import org.whispersystems.textsecuregcm.storage.DynamoDbExtensionSchema.Tables; import org.whispersystems.textsecuregcm.tests.util.DevicesHelper; import org.whispersystems.textsecuregcm.tests.util.JsonHelpers; @@ -137,7 +136,6 @@ class AccountsManagerConcurrentModificationIntegrationTest { mock(ProfilesManager.class), mock(SecureStorageClient.class), mock(SecureValueRecovery2Client.class), - mock(SecureValueRecovery3Client.class), mock(DisconnectionRequestManager.class), mock(RegistrationRecoveryPasswordsManager.class), mock(ClientPublicKeysManager.class), diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerDeviceTransferIntegrationTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerDeviceTransferIntegrationTest.java index 0f2780b14..bd360e103 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerDeviceTransferIntegrationTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerDeviceTransferIntegrationTest.java @@ -21,7 +21,7 @@ import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClusterClient; import org.whispersystems.textsecuregcm.redis.RedisServerExtension; import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client; -import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery3Client; + import java.nio.charset.StandardCharsets; import java.time.Clock; import java.time.Duration; @@ -66,7 +66,6 @@ public class AccountsManagerDeviceTransferIntegrationTest { mock(ProfilesManager.class), mock(SecureStorageClient.class), mock(SecureValueRecovery2Client.class), - mock(SecureValueRecovery3Client.class), mock(DisconnectionRequestManager.class), mock(RegistrationRecoveryPasswordsManager.class), mock(ClientPublicKeysManager.class), diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java index b1077c168..704118d06 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java @@ -87,7 +87,6 @@ import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClient; import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClusterClient; import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client; -import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery3Client; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecoveryException; import org.whispersystems.textsecuregcm.storage.AccountsManager.UsernameReservation; import org.whispersystems.textsecuregcm.tests.util.AccountsHelper; @@ -131,7 +130,6 @@ class AccountsManagerTest { private RedisAdvancedClusterAsyncCommands asyncClusterCommands; private AccountsManager accountsManager; private SecureValueRecovery2Client svr2Client; - private SecureValueRecovery3Client svr3Client; private DynamicConfiguration dynamicConfiguration; private static final Answer ACCOUNT_UPDATE_ANSWER = (answer) -> { @@ -195,9 +193,6 @@ class AccountsManagerTest { svr2Client = mock(SecureValueRecovery2Client.class); when(svr2Client.deleteBackups(any())).thenReturn(CompletableFuture.completedFuture(null)); - svr3Client = mock(SecureValueRecovery3Client.class); - when(svr3Client.deleteBackups(any())).thenReturn(CompletableFuture.completedFuture(null)); - final PhoneNumberIdentifiers phoneNumberIdentifiers = mock(PhoneNumberIdentifiers.class); phoneNumberIdentifiersByE164 = new HashMap<>(); @@ -259,7 +254,6 @@ class AccountsManagerTest { profilesManager, storageClient, svr2Client, - svr3Client, disconnectionRequestManager, registrationRecoveryPasswordsManager, clientPublicKeysManager, @@ -295,19 +289,6 @@ class AccountsManagerTest { ); } - @ParameterizedTest - @ValueSource(strings = {"500", "429"}) - void testDeleteWithSvr3ErrorStatusCodes(final String statusCode) throws InterruptedException { - when(svr3Client.deleteBackups(any())).thenReturn( - CompletableFuture.failedFuture(new SecureValueRecoveryException("Failed to delete backup", statusCode))); - - final AccountAttributes attributes = new AccountAttributes(false, 1, 2, null, null, true, null); - - final Account createdAccount = createAccount("+18005550123", attributes); - - assertDoesNotThrow(() -> accountsManager.delete(createdAccount, AccountsManager.DeletionReason.USER_REQUEST).toCompletableFuture().join()); - } - @Test void testGetByServiceIdentifier() { final UUID aci = UUID.randomUUID(); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerUsernameIntegrationTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerUsernameIntegrationTest.java index e145b2f9b..523015337 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerUsernameIntegrationTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerUsernameIntegrationTest.java @@ -41,7 +41,6 @@ import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClient; import org.whispersystems.textsecuregcm.redis.RedisClusterExtension; import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client; -import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery3Client; import org.whispersystems.textsecuregcm.storage.DynamoDbExtensionSchema.Tables; import org.whispersystems.textsecuregcm.tests.util.AccountsHelper; import org.whispersystems.textsecuregcm.util.AttributeValues; @@ -151,7 +150,6 @@ class AccountsManagerUsernameIntegrationTest { profileManager, mock(SecureStorageClient.class), mock(SecureValueRecovery2Client.class), - mock(SecureValueRecovery3Client.class), disconnectionRequestManager, mock(RegistrationRecoveryPasswordsManager.class), mock(ClientPublicKeysManager.class), diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java index 1d6ad01f5..91f7d4b56 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java @@ -467,7 +467,6 @@ class AccountsTest { // the backup credential request and share-set are always preserved across account reclaims existingAccount.setBackupCredentialRequests(TestRandomUtil.nextBytes(32), TestRandomUtil.nextBytes(32)); - existingAccount.setSvr3ShareSet(TestRandomUtil.nextBytes(100)); createAccount(existingAccount); final Account secondAccount = generateAccount(e164, UUID.randomUUID(), UUID.randomUUID(), List.of(generateDevice(DEVICE_ID_1))); @@ -479,7 +478,6 @@ class AccountsTest { .isEqualTo(existingAccount.getBackupCredentialRequest(BackupCredentialType.MESSAGES).get()); assertThat(reclaimed.getBackupCredentialRequest(BackupCredentialType.MEDIA).get()) .isEqualTo(existingAccount.getBackupCredentialRequest(BackupCredentialType.MEDIA).get()); - assertThat(reclaimed.getSvr3ShareSet()).isEqualTo(existingAccount.getSvr3ShareSet()); } @Test diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AddRemoveDeviceIntegrationTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AddRemoveDeviceIntegrationTest.java index 9e7bd7292..cf64e9904 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AddRemoveDeviceIntegrationTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AddRemoveDeviceIntegrationTest.java @@ -41,7 +41,6 @@ import org.whispersystems.textsecuregcm.redis.RedisClusterExtension; import org.whispersystems.textsecuregcm.redis.RedisServerExtension; import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient; import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client; -import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery3Client; import org.whispersystems.textsecuregcm.tests.util.AccountsHelper; import org.whispersystems.textsecuregcm.tests.util.KeysHelper; import org.whispersystems.textsecuregcm.util.Pair; @@ -126,9 +125,6 @@ public class AddRemoveDeviceIntegrationTest { final SecureValueRecovery2Client svr2Client = mock(SecureValueRecovery2Client.class); when(svr2Client.deleteBackups(any())).thenReturn(CompletableFuture.completedFuture(null)); - final SecureValueRecovery3Client svr3Client = mock(SecureValueRecovery3Client.class); - when(svr3Client.deleteBackups(any())).thenReturn(CompletableFuture.completedFuture(null)); - final PhoneNumberIdentifiers phoneNumberIdentifiers = new PhoneNumberIdentifiers(DYNAMO_DB_EXTENSION.getDynamoDbAsyncClient(), DynamoDbExtensionSchema.Tables.PNI.tableName()); @@ -161,7 +157,6 @@ public class AddRemoveDeviceIntegrationTest { profilesManager, secureStorageClient, svr2Client, - svr3Client, mock(DisconnectionRequestManager.class), mock(RegistrationRecoveryPasswordsManager.class), clientPublicKeysManager, diff --git a/service/src/test/resources/config/test-secrets-bundle.yml b/service/src/test/resources/config/test-secrets-bundle.yml index 9f4df96e1..7d2932157 100644 --- a/service/src/test/resources/config/test-secrets-bundle.yml +++ b/service/src/test/resources/config/test-secrets-bundle.yml @@ -53,9 +53,6 @@ directoryV2.client.userIdTokenSharedSecret: bbcdefghijklmnopqrstuvwxyz0123456789 svr2.userAuthenticationTokenSharedSecret: abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with SVR2 to generate auth tokens for Signal users svr2.userIdTokenSharedSecret: bbcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with SVR2 to generate auth identity tokens for Signal users -svr3.userAuthenticationTokenSharedSecret: cbcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with SVR3 to generate auth tokens for Signal users -svr3.userIdTokenSharedSecret: dbcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with SVR3 to generate auth identity tokens for Signal users - tus.userAuthenticationTokenSharedSecret: abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # The below private key was key generated exclusively for testing purposes. Do not use it in any other context. diff --git a/service/src/test/resources/config/test.yml b/service/src/test/resources/config/test.yml index f1c696ebc..58f56f527 100644 --- a/service/src/test/resources/config/test.yml +++ b/service/src/test/resources/config/test.yml @@ -217,37 +217,6 @@ svr2: 9Kxq0DY7RCEpdHMCKcOL -----END CERTIFICATE----- -svr3: - backend1Uri: backend1.example.com - backend2Uri: backend2.example.com - backend3Uri: backend3.example.com - userAuthenticationTokenSharedSecret: secret://svr3.userAuthenticationTokenSharedSecret - userIdTokenSharedSecret: secret://svr3.userIdTokenSharedSecret - svrCaCertificates: - # This is a randomly generated test certificate - - | - -----BEGIN CERTIFICATE----- - MIIDazCCAlOgAwIBAgIUW5lcNWkuynRVc8Rq5pO6mHQBuZAwDQYJKoZIhvcNAQEL - BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM - GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDAzMjUwMzE4MTNaFw0yOTAz - MjQwMzE4MTNaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw - HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB - AQUAA4IBDwAwggEKAoIBAQCfH4Um+fv2r4KudhD37/UXp8duRLTmp4XvpBTpDHpD - 2HF8p2yThVKlJnMkP/9Ey1Rb0vhxO7DCltLdW8IYcxJuHoyMvyhGUEtxxkOZbrk8 - ciUR9jTZ37x7vXRGj/RxcdlS6iD0MeF0D/LAkImt4T/kiKwDbENrVEnYWJmipCKP - ribxWky7HqxDCoYMQr0zatxB3A9mx5stH+H3kbw3CZcm+ugF9ZIKDEVHb0lf28gq - llmD120q/vs9YV3rzVL7sBGDqf6olkulvHQJKElZg2rdcHWFcngSlU2BjR04oyuH - c/SSiLSB3YB0tdFGta5uorXyV1y7RElPeBfOfvEjsG3TAgMBAAGjUzBRMB0GA1Ud - DgQWBBQX+xlgSWWbDjv0SrJ+h67xauJ80zAfBgNVHSMEGDAWgBQX+xlgSWWbDjv0 - SrJ+h67xauJ80zAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAw - ZG2MCCjscn6h/QOoJU+IDfa68OqLq0I37gMnLMde4yEhAmm//miePIq4Uz9GRJ+h - rAmdEnspKgyQ93PjF7Xpk/JdJA4B1bIrsOl/cSwqx2sFhRt8Kt1DHGlGWXqOaHRP - UkZ86MyRL3sXly6WkxEYxZJeQaOzMy2XmQh7grzrlTBuSI+0xf7vsRRDipxr6LVQ - 6qGWyGODLLc2JD1IXj/1HpRVT2LoGGlKMuyxACQAm4oak1vvJ9mGxgfd9AU+eo58 - O/esB2Eaf+QqMPELdFSZQfG2jvp+3WQTZK8fDKHyLr076G3UetEMy867F6fzTSZd - 9Kxq0DY7RCEpdHMCKcOL - -----END CERTIFICATE----- - messageCache: # Redis server configuration for message store cache persistDelayMinutes: 1 cluster: