From 9cfd88a23fdbaa2ee2af7b409b9804b4e377fd3a Mon Sep 17 00:00:00 2001 From: Jon Chambers Date: Mon, 12 Jun 2023 16:25:39 -0400 Subject: [PATCH] Move turn secret to static configuration --- service/config/sample-secrets-bundle.yml | 2 ++ service/config/sample.yml | 3 +++ .../WhisperServerConfiguration.java | 10 ++++++++++ .../textsecuregcm/WhisperServerService.java | 3 ++- .../auth/TurnTokenGenerator.java | 19 ++++++++++++------- .../TurnSecretConfiguration.java | 11 +++++++++++ .../dynamic/DynamicTurnConfiguration.java | 7 ------- .../auth/TurnTokenGeneratorTest.java | 14 +++++++++----- .../dynamic/DynamicConfigurationTest.java | 2 -- 9 files changed, 49 insertions(+), 22 deletions(-) create mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/configuration/TurnSecretConfiguration.java diff --git a/service/config/sample-secrets-bundle.yml b/service/config/sample-secrets-bundle.yml index 035584704..613bf5823 100644 --- a/service/config/sample-secrets-bundle.yml +++ b/service/config/sample-secrets-bundle.yml @@ -84,3 +84,5 @@ artService.userAuthenticationTokenUserIdSecret: AAAAAAAAAAA= # base64-encoded se currentReportingKey.secret: AAAAAAAAAAA= currentReportingKey.salt: AAAAAAAAAAA= + +turn.secret: AAAAAAAAAAA= diff --git a/service/config/sample.yml b/service/config/sample.yml index 0f4605980..20485f510 100644 --- a/service/config/sample.yml +++ b/service/config/sample.yml @@ -419,3 +419,6 @@ registrationService: ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz AAAAAAAAAAAAAAAAAAAA -----END CERTIFICATE----- + +turn: + secret: secret://turn.secret diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java index b70c747ca..06eded1b6 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java @@ -47,6 +47,7 @@ import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery2Config import org.whispersystems.textsecuregcm.configuration.SpamFilterConfiguration; import org.whispersystems.textsecuregcm.configuration.StripeConfiguration; import org.whispersystems.textsecuregcm.configuration.SubscriptionConfiguration; +import org.whispersystems.textsecuregcm.configuration.TurnSecretConfiguration; import org.whispersystems.textsecuregcm.configuration.UnidentifiedDeliveryConfiguration; import org.whispersystems.textsecuregcm.configuration.ZkConfig; import org.whispersystems.textsecuregcm.limits.RateLimiterConfig; @@ -264,6 +265,11 @@ public class WhisperServerConfiguration extends Configuration { @JsonProperty private RegistrationServiceConfiguration registrationService; + @Valid + @NotNull + @JsonProperty + private TurnSecretConfiguration turn; + public AdminEventLoggingConfiguration getAdminEventLoggingConfiguration() { return adminEventLoggingConfiguration; } @@ -438,4 +444,8 @@ public class WhisperServerConfiguration extends Configuration { public RegistrationServiceConfiguration getRegistrationServiceConfiguration() { return registrationService; } + + public TurnSecretConfiguration getTurnSecretConfiguration() { + return turn; + } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index 62b809492..fc571bb5f 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -554,7 +554,8 @@ public class WhisperServerService extends Application dynamicConfiguration; + private final DynamicConfigurationManager dynamicConfigurationManager; + + private final byte[] turnSecret; private static final String ALGORITHM = "HmacSHA1"; - public TurnTokenGenerator(final DynamicConfigurationManager config) { - this.dynamicConfiguration = config; + public TurnTokenGenerator(final DynamicConfigurationManager dynamicConfigurationManager, + final byte[] turnSecret) { + + this.dynamicConfigurationManager = dynamicConfigurationManager; + this.turnSecret = turnSecret; } public TurnToken generate(final String e164) { try { - final byte[] key = dynamicConfiguration.getConfiguration().getTurnConfiguration().getSecret().getBytes(); final List urls = urls(e164); final Mac mac = Mac.getInstance(ALGORITHM); final long validUntilSeconds = Instant.now().plus(Duration.ofDays(1)).getEpochSecond(); final long user = Util.ensureNonNegativeInt(new SecureRandom().nextInt()); final String userTime = validUntilSeconds + ":" + user; - mac.init(new SecretKeySpec(key, ALGORITHM)); + mac.init(new SecretKeySpec(turnSecret, ALGORITHM)); final String password = Base64.getEncoder().encodeToString(mac.doFinal(userTime.getBytes())); return new TurnToken(userTime, password, urls); - } catch (NoSuchAlgorithmException | InvalidKeyException e) { + } catch (final NoSuchAlgorithmException | InvalidKeyException e) { throw new AssertionError(e); } } private List urls(final String e164) { - final DynamicTurnConfiguration turnConfig = dynamicConfiguration.getConfiguration().getTurnConfiguration(); + final DynamicTurnConfiguration turnConfig = dynamicConfigurationManager.getConfiguration().getTurnConfiguration(); // Check if number is enrolled to test out specific turn servers final Optional enrolled = turnConfig.getUriConfigs().stream() .filter(config -> config.getEnrolledNumbers().contains(e164)) .findFirst(); + if (enrolled.isPresent()) { return enrolled.get().getUris(); } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/TurnSecretConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/TurnSecretConfiguration.java new file mode 100644 index 000000000..496780e93 --- /dev/null +++ b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/TurnSecretConfiguration.java @@ -0,0 +1,11 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.whispersystems.textsecuregcm.configuration; + +import org.whispersystems.textsecuregcm.configuration.secrets.SecretBytes; + +public record TurnSecretConfiguration(SecretBytes secret) { +} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicTurnConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicTurnConfiguration.java index 524898eb5..e34a2143a 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicTurnConfiguration.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicTurnConfiguration.java @@ -13,17 +13,10 @@ import org.whispersystems.textsecuregcm.configuration.TurnUriConfiguration; public class DynamicTurnConfiguration { - @JsonProperty - private String secret; - @JsonProperty private List<@Valid TurnUriConfiguration> uriConfigs = Collections.emptyList(); public List getUriConfigs() { return uriConfigs; } - - public String getSecret() { - return secret; - } } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/TurnTokenGeneratorTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/TurnTokenGeneratorTest.java index 927e19696..bce5e7637 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/auth/TurnTokenGeneratorTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/TurnTokenGeneratorTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test; import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration; import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager; +import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -21,7 +22,6 @@ public class TurnTokenGeneratorTest { captcha: scoreFloor: 1.0 turn: - secret: bloop uriConfigs: - uris: - always1.org @@ -39,7 +39,9 @@ public class TurnTokenGeneratorTest { DynamicConfigurationManager.class); when(mockDynamicConfigManager.getConfiguration()).thenReturn(config); - final TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(mockDynamicConfigManager); + + final TurnTokenGenerator turnTokenGenerator = + new TurnTokenGenerator(mockDynamicConfigManager, "bloop".getBytes(StandardCharsets.UTF_8)); final long COUNT = 1000; @@ -60,7 +62,6 @@ public class TurnTokenGeneratorTest { captcha: scoreFloor: 1.0 turn: - secret: bloop uriConfigs: - uris: - always.org @@ -80,7 +81,8 @@ public class TurnTokenGeneratorTest { DynamicConfigurationManager.class); when(mockDynamicConfigManager.getConfiguration()).thenReturn(config); - final TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(mockDynamicConfigManager); + final TurnTokenGenerator turnTokenGenerator = + new TurnTokenGenerator(mockDynamicConfigManager, "bloop".getBytes(StandardCharsets.UTF_8)); final long COUNT = 1000; @@ -122,7 +124,9 @@ public class TurnTokenGeneratorTest { when(mockDynamicConfigManager.getConfiguration()).thenReturn(config); - final TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(mockDynamicConfigManager); + final TurnTokenGenerator turnTokenGenerator = + new TurnTokenGenerator(mockDynamicConfigManager, "bloop".getBytes(StandardCharsets.UTF_8)); + TurnToken token = turnTokenGenerator.generate("+15555555555"); assertThat(token.getUrls().get(0)).isEqualTo("enrolled.org"); token = turnTokenGenerator.generate("+15555555556"); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfigurationTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfigurationTest.java index ba74ec150..49f8b25a5 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfigurationTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfigurationTest.java @@ -329,7 +329,6 @@ class DynamicConfigurationTest { { final String config = REQUIRED_CONFIG.concat(""" turn: - secret: bloop uriConfigs: - uris: - turn:test0.org @@ -344,7 +343,6 @@ class DynamicConfigurationTest { .parseConfiguration(config, DynamicConfiguration.class) .orElseThrow() .getTurnConfiguration(); - assertThat(turnConfiguration.getSecret()).isEqualTo("bloop"); assertThat(turnConfiguration.getUriConfigs().get(0).getUris()).hasSize(2); assertThat(turnConfiguration.getUriConfigs().get(1).getUris()).hasSize(1); assertThat(turnConfiguration.getUriConfigs().get(0).getWeight()).isEqualTo(1);