Add auth controller for SVR3 to /v3/backup.
This commit is contained in:
parent
c18aca9215
commit
22e6584402
|
@ -11,6 +11,9 @@ directoryV2.client.userIdTokenSharedSecret: bbcdefghijklmnopqrstuvwxyz0123456789
|
||||||
svr2.userAuthenticationTokenSharedSecret: abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG= # base64-encoded secret shared with SVR2 to generate auth tokens for Signal users
|
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
|
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=
|
tus.userAuthenticationTokenSharedSecret: abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG=
|
||||||
|
|
||||||
awsAttachments.accessKey: test
|
awsAttachments.accessKey: test
|
||||||
|
|
|
@ -179,6 +179,34 @@ svr2:
|
||||||
AAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAA
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
svr3:
|
||||||
|
uri: svr3.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
|
messageCache: # Redis server configuration for message store cache
|
||||||
persistDelayMinutes: 1
|
persistDelayMinutes: 1
|
||||||
|
|
|
@ -49,6 +49,7 @@ import org.whispersystems.textsecuregcm.configuration.RemoteConfigConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.ReportMessageConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.ReportMessageConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.SecureStorageServiceConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.SecureStorageServiceConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery2Configuration;
|
import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery2Configuration;
|
||||||
|
import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery3Configuration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.ShortCodeExpanderConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.ShortCodeExpanderConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.SpamFilterConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.SpamFilterConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.StripeConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.StripeConfiguration;
|
||||||
|
@ -136,6 +137,10 @@ public class WhisperServerConfiguration extends Configuration {
|
||||||
@Valid
|
@Valid
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private SecureValueRecovery2Configuration svr2;
|
private SecureValueRecovery2Configuration svr2;
|
||||||
|
@NotNull
|
||||||
|
@Valid
|
||||||
|
@JsonProperty
|
||||||
|
private SecureValueRecovery3Configuration svr3;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Valid
|
@Valid
|
||||||
|
@ -367,9 +372,13 @@ public class WhisperServerConfiguration extends Configuration {
|
||||||
return metricsCluster;
|
return metricsCluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public SecureValueRecovery2Configuration getSvr2Configuration() {
|
public SecureValueRecovery2Configuration getSvr2Configuration() {
|
||||||
return svr2;
|
return svr2;
|
||||||
}
|
}
|
||||||
|
public SecureValueRecovery3Configuration getSvr3Configuration() {
|
||||||
|
return svr3;
|
||||||
|
}
|
||||||
|
|
||||||
public DirectoryV2Configuration getDirectoryV2Configuration() {
|
public DirectoryV2Configuration getDirectoryV2Configuration() {
|
||||||
return directoryV2;
|
return directoryV2;
|
||||||
|
|
|
@ -116,6 +116,7 @@ import org.whispersystems.textsecuregcm.controllers.RegistrationController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.RemoteConfigController;
|
import org.whispersystems.textsecuregcm.controllers.RemoteConfigController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.SecureStorageController;
|
import org.whispersystems.textsecuregcm.controllers.SecureStorageController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.SecureValueRecovery2Controller;
|
import org.whispersystems.textsecuregcm.controllers.SecureValueRecovery2Controller;
|
||||||
|
import org.whispersystems.textsecuregcm.controllers.SecureValueRecovery3Controller;
|
||||||
import org.whispersystems.textsecuregcm.controllers.StickerController;
|
import org.whispersystems.textsecuregcm.controllers.StickerController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.SubscriptionController;
|
import org.whispersystems.textsecuregcm.controllers.SubscriptionController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.VerificationController;
|
import org.whispersystems.textsecuregcm.controllers.VerificationController;
|
||||||
|
@ -496,7 +497,9 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
ExternalServiceCredentialsGenerator artCredentialsGenerator = ArtController.credentialsGenerator(
|
ExternalServiceCredentialsGenerator artCredentialsGenerator = ArtController.credentialsGenerator(
|
||||||
config.getArtServiceConfiguration());
|
config.getArtServiceConfiguration());
|
||||||
ExternalServiceCredentialsGenerator svr2CredentialsGenerator = SecureValueRecovery2Controller.credentialsGenerator(
|
ExternalServiceCredentialsGenerator svr2CredentialsGenerator = SecureValueRecovery2Controller.credentialsGenerator(
|
||||||
config.getSvr2Configuration());
|
config.getSvr2Configuration());
|
||||||
|
ExternalServiceCredentialsGenerator svr3CredentialsGenerator = SecureValueRecovery3Controller.credentialsGenerator(
|
||||||
|
config.getSvr3Configuration());
|
||||||
|
|
||||||
dynamicConfigurationManager.start();
|
dynamicConfigurationManager.start();
|
||||||
|
|
||||||
|
@ -831,6 +834,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
clock),
|
clock),
|
||||||
new SecureStorageController(storageCredentialsGenerator),
|
new SecureStorageController(storageCredentialsGenerator),
|
||||||
new SecureValueRecovery2Controller(svr2CredentialsGenerator, accountsManager),
|
new SecureValueRecovery2Controller(svr2CredentialsGenerator, accountsManager),
|
||||||
|
new SecureValueRecovery3Controller(svr3CredentialsGenerator, accountsManager),
|
||||||
new StickerController(rateLimiters, config.getCdnConfiguration().accessKey().value(),
|
new StickerController(rateLimiters, config.getCdnConfiguration().accessKey().value(),
|
||||||
config.getCdnConfiguration().accessSecret().value(), config.getCdnConfiguration().region(),
|
config.getCdnConfiguration().accessSecret().value(), config.getCdnConfiguration().region(),
|
||||||
config.getCdnConfiguration().bucket()),
|
config.getCdnConfiguration().bucket()),
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
package org.whispersystems.textsecuregcm.configuration;
|
||||||
|
|
||||||
|
import org.whispersystems.textsecuregcm.configuration.secrets.SecretBytes;
|
||||||
|
import org.whispersystems.textsecuregcm.util.ExactlySize;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record SecureValueRecovery3Configuration(
|
||||||
|
@NotBlank String uri,
|
||||||
|
@ExactlySize(32) SecretBytes userAuthenticationTokenSharedSecret,
|
||||||
|
@ExactlySize(32) SecretBytes userIdTokenSharedSecret,
|
||||||
|
@NotEmpty List<@NotBlank String> svrCaCertificates,
|
||||||
|
@NotNull @Valid CircuitBreakerConfiguration circuitBreaker,
|
||||||
|
@NotNull @Valid RetryConfiguration retry) {
|
||||||
|
|
||||||
|
public SecureValueRecovery3Configuration {
|
||||||
|
if (circuitBreaker == null) {
|
||||||
|
circuitBreaker = new CircuitBreakerConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retry == null) {
|
||||||
|
retry = new RetryConfiguration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.controllers;
|
package org.whispersystems.textsecuregcm.controllers;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import io.dropwizard.auth.Auth;
|
import io.dropwizard.auth.Auth;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
@ -22,7 +23,6 @@ import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.jetbrains.annotations.TestOnly;
|
|
||||||
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
|
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
|
||||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials;
|
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials;
|
||||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator;
|
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator;
|
||||||
|
@ -45,7 +45,7 @@ public class SecureValueRecovery2Controller {
|
||||||
return credentialsGenerator(cfg, Clock.systemUTC());
|
return credentialsGenerator(cfg, Clock.systemUTC());
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestOnly
|
@VisibleForTesting
|
||||||
public static ExternalServiceCredentialsGenerator credentialsGenerator(final SecureValueRecovery2Configuration cfg, final Clock clock) {
|
public static ExternalServiceCredentialsGenerator credentialsGenerator(final SecureValueRecovery2Configuration cfg, final Clock clock) {
|
||||||
return ExternalServiceCredentialsGenerator
|
return ExternalServiceCredentialsGenerator
|
||||||
.builder(cfg.userAuthenticationTokenSharedSecret())
|
.builder(cfg.userAuthenticationTokenSharedSecret())
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
* 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 org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
|
||||||
|
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.AuthCheckResponse;
|
||||||
|
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 java.time.Clock;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
@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).
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
@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) {
|
||||||
|
return backupServiceCredentialGenerator.generateFor(auth.getAccount().getUuid().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@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 AuthCheckResponse authCheck(@NotNull @Valid final AuthCheckRequest request) {
|
||||||
|
final List<ExternalServiceCredentialsSelector.CredentialInfo> credentials = ExternalServiceCredentialsSelector.check(
|
||||||
|
request.passwords(),
|
||||||
|
backupServiceCredentialGenerator,
|
||||||
|
MAX_AGE_SECONDS);
|
||||||
|
|
||||||
|
// the username associated with the provided number
|
||||||
|
final Optional<String> matchingUsername = accountsManager
|
||||||
|
.getByE164(request.number())
|
||||||
|
.map(Account::getUuid)
|
||||||
|
.map(backupServiceCredentialGenerator::generateForUuid)
|
||||||
|
.map(ExternalServiceCredentials::username);
|
||||||
|
|
||||||
|
return new AuthCheckResponse(credentials.stream().collect(Collectors.toMap(
|
||||||
|
ExternalServiceCredentialsSelector.CredentialInfo::token,
|
||||||
|
info -> {
|
||||||
|
if (!info.valid()) {
|
||||||
|
return AuthCheckResponse.Result.INVALID;
|
||||||
|
}
|
||||||
|
final String username = info.credentials().username();
|
||||||
|
// does this credential match the account id for the e164 provided in the request?
|
||||||
|
boolean match = matchingUsername.filter(username::equals).isPresent();
|
||||||
|
return match ? AuthCheckResponse.Result.MATCH : AuthCheckResponse.Result.NO_MATCH;
|
||||||
|
}
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.whispersystems.textsecuregcm.controllers;
|
||||||
|
|
||||||
|
|
||||||
|
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
|
||||||
|
import io.dropwizard.testing.junit5.ResourceExtension;
|
||||||
|
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator;
|
||||||
|
import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery2Configuration;
|
||||||
|
import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery3Configuration;
|
||||||
|
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 static org.mockito.Mockito.mock;
|
||||||
|
import static org.whispersystems.textsecuregcm.util.MockUtils.randomSecretBytes;
|
||||||
|
|
||||||
|
@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())
|
||||||
|
.setMapper(SystemMapper.jsonMapper())
|
||||||
|
.setTestContainerFactory(new GrizzlyWebTestContainerFactory())
|
||||||
|
.addResource(CONTROLLER)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
protected SecureValueRecovery3ControllerTest() {
|
||||||
|
super("/v3", ACCOUNTS_MANAGER, CLOCK, RESOURCES, CREDENTIAL_GENERATOR);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue