From 0cc84131de748b0f3c246fe92b9657968c22408a Mon Sep 17 00:00:00 2001 From: Chris Eager Date: Tue, 28 Mar 2023 16:39:35 -0500 Subject: [PATCH] Add `enabled` to SVR2 configuration --- service/config/sample.yml | 1 + .../textsecuregcm/WhisperServerService.java | 2 +- .../SecureValueRecovery2Configuration.java | 5 +++-- .../SecureValueRecovery2Controller.java | 9 ++++++++- .../SecureValueRecovery2Client.java | 7 +++++++ .../SecureValueRecoveryException.java | 2 +- .../SecureValueRecovery2ClientTest.java | 17 ++++++++++------- 7 files changed, 31 insertions(+), 12 deletions(-) diff --git a/service/config/sample.yml b/service/config/sample.yml index 8a4255e3d..5b2dd8329 100644 --- a/service/config/sample.yml +++ b/service/config/sample.yml @@ -146,6 +146,7 @@ directoryV2: userIdTokenSharedSecret: bbcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with CDS to generate auth identity tokens for Signal users svr2: + enabled: false uri: svr2.example.com userAuthenticationTokenSharedSecret: abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with SVR2 to generate auth tokens for Signal users userIdTokenSharedSecret: bbcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with SVR2 to generate auth identity tokens for Signal users diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index ac24d9fcf..6f3da497b 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -796,7 +796,7 @@ public class WhisperServerService extends Application svrCaCertificates, @NotNull @Valid CircuitBreakerConfiguration circuitBreaker, @NotNull @Valid RetryConfiguration retry) { diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery2Controller.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery2Controller.java index 2160a87c4..5ac1e977a 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery2Controller.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SecureValueRecovery2Controller.java @@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.GET; +import javax.ws.rs.NotFoundException; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @@ -32,9 +33,12 @@ public class SecureValueRecovery2Controller { } private final ExternalServiceCredentialsGenerator backupServiceCredentialGenerator; + private final boolean enabled; - public SecureValueRecovery2Controller(final ExternalServiceCredentialsGenerator backupServiceCredentialGenerator) { + public SecureValueRecovery2Controller(final ExternalServiceCredentialsGenerator backupServiceCredentialGenerator, + final SecureValueRecovery2Configuration cfg) { this.backupServiceCredentialGenerator = backupServiceCredentialGenerator; + this.enabled = cfg.enabled(); } @Timed @@ -51,6 +55,9 @@ public class SecureValueRecovery2Controller { @ApiResponse(responseCode = "200", description = "`JSON` with generated credentials.", useReturnTypeSchema = true) @ApiResponse(responseCode = "401", description = "Account authentication check failed.") public ExternalServiceCredentials getAuth(@Auth final AuthenticatedAccount auth) { + if (!enabled) { + throw new NotFoundException(); + } return backupServiceCredentialGenerator.generateFor(auth.getAccount().getUuid().toString()); } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery2Client.java b/service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery2Client.java index 0eb5c25ba..e9ac9bdd6 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery2Client.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery2Client.java @@ -32,6 +32,7 @@ public class SecureValueRecovery2Client { private final ExternalServiceCredentialsGenerator secureValueRecoveryCredentialsGenerator; private final URI deleteUri; private final FaultTolerantHttpClient httpClient; + private final boolean enabled; @VisibleForTesting static final String DELETE_PATH = "/v1/delete"; @@ -52,9 +53,15 @@ public class SecureValueRecovery2Client { .withSecurityProtocol(FaultTolerantHttpClient.SECURITY_PROTOCOL_TLS_1_2) .withTrustedServerCertificates(configuration.svrCaCertificates().toArray(new String[0])) .build(); + this.enabled = configuration.enabled(); } public CompletableFuture deleteBackups(final UUID accountUuid) { + + if (!enabled) { + return CompletableFuture.completedFuture(null); + } + final ExternalServiceCredentials credentials = secureValueRecoveryCredentialsGenerator.generateForUuid(accountUuid); final HttpRequest request = HttpRequest.newBuilder() diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecoveryException.java b/service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecoveryException.java index 5bbdf2ba5..e6a3a9b70 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecoveryException.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecoveryException.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 Signal Messenger, LLC + * Copyright 2023 Signal Messenger, LLC * SPDX-License-Identifier: AGPL-3.0-only */ diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery2ClientTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery2ClientTest.java index c749b130b..6e8b9cdd7 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery2ClientTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecovery2ClientTest.java @@ -9,6 +9,7 @@ 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; @@ -50,8 +51,11 @@ class SecureValueRecovery2ClientTest { credentialsGenerator = mock(ExternalServiceCredentialsGenerator.class); httpExecutor = Executors.newSingleThreadExecutor(); - final SecureValueRecovery2Configuration config = new SecureValueRecovery2Configuration(new byte[0], new byte[0], - "http://localhost:" + wireMock.getPort(), List.of(""" + final SecureValueRecovery2Configuration config = new SecureValueRecovery2Configuration(true, + "http://localhost:" + wireMock.getPort(), + new byte[0], new byte[0], + // This is a randomly-generated, throwaway certificate that's not actually connected to anything + List.of(""" -----BEGIN CERTIFICATE----- MIICZDCCAc2gAwIBAgIBADANBgkqhkiG9w0BAQ0FADBPMQswCQYDVQQGEwJ1czEL MAkGA1UECAwCVVMxHjAcBgNVBAoMFVNpZ25hbCBNZXNzZW5nZXIsIExMQzETMBEG @@ -67,8 +71,7 @@ class SecureValueRecovery2ClientTest { y7MTM4NoBV1k0zb5LAk89SIDPr/maW5AsLtEomzjnEiomjoMBUdNe3YCgQReoLnr R/QaUNbrCjTGYfBsjGbIzmkWPUyTec2ZdRyJ8JiVl386+6CZkxnndQ== -----END CERTIFICATE----- - """, - """ + """, """ -----BEGIN CERTIFICATE----- MIIEpDCCAowCCQC43PUTWSADVjANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAls b2NhbGhvc3QwHhcNMjIxMDE3MjA0NTM0WhcNMjMxMDE3MjA0NTM0WjAUMRIwEAYD @@ -96,7 +99,8 @@ class SecureValueRecovery2ClientTest { WIOjZOKGW690ESKCKOnFjUHVO0HpuWnT81URTuY62FXsYdVc2wE4v0E04mEbqQ0P lY6ZKNA81Lm3YADYtObmK1IUrOPo9BeIaPy0UM08SmN880Vunqa91Q== -----END CERTIFICATE----- - """), null, null); + """), + null, null); secureValueRecovery2Client = new SecureValueRecovery2Client(credentialsGenerator, httpExecutor, config); } @@ -119,8 +123,7 @@ class SecureValueRecovery2ClientTest { .withBasicAuth(username, password) .willReturn(aResponse().withStatus(202))); - // We're happy as long as this doesn't throw an exception - secureValueRecovery2Client.deleteBackups(accountUuid).join(); + assertDoesNotThrow(() -> secureValueRecovery2Client.deleteBackups(accountUuid).join()); } @Test