Add new event logging module

This commit is contained in:
Ehren Kret 2022-08-26 11:52:45 -05:00
parent 6119b6ab89
commit a4508ec84f
9 changed files with 139 additions and 9 deletions

View File

@ -1135,7 +1135,7 @@ ij_kotlin_field_annotation_wrap = split_into_lines
ij_kotlin_finally_on_new_line = false ij_kotlin_finally_on_new_line = false
ij_kotlin_if_rparen_on_new_line = false ij_kotlin_if_rparen_on_new_line = false
ij_kotlin_import_nested_classes = false ij_kotlin_import_nested_classes = false
ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^ ij_kotlin_imports_layout = *
ij_kotlin_insert_whitespaces_in_simple_one_line_method = true ij_kotlin_insert_whitespaces_in_simple_one_line_method = true
ij_kotlin_keep_blank_lines_before_right_brace = 2 ij_kotlin_keep_blank_lines_before_right_brace = 2
ij_kotlin_keep_blank_lines_in_code = 2 ij_kotlin_keep_blank_lines_in_code = 2
@ -1151,9 +1151,9 @@ ij_kotlin_method_call_chain_wrap = off
ij_kotlin_method_parameters_new_line_after_left_paren = false ij_kotlin_method_parameters_new_line_after_left_paren = false
ij_kotlin_method_parameters_right_paren_on_new_line = false ij_kotlin_method_parameters_right_paren_on_new_line = false
ij_kotlin_method_parameters_wrap = off ij_kotlin_method_parameters_wrap = off
ij_kotlin_name_count_to_use_star_import = 5 ij_kotlin_name_count_to_use_star_import = 999
ij_kotlin_name_count_to_use_star_import_for_members = 3 ij_kotlin_name_count_to_use_star_import_for_members = 999
ij_kotlin_packages_to_use_import_on_demand = java.util.*,kotlinx.android.synthetic.**,io.ktor.** ij_kotlin_packages_to_use_import_on_demand =
ij_kotlin_parameter_annotation_wrap = off ij_kotlin_parameter_annotation_wrap = off
ij_kotlin_space_after_comma = true ij_kotlin_space_after_comma = true
ij_kotlin_space_after_extend_colon = true ij_kotlin_space_after_extend_colon = true

77
event-logger/pom.xml Normal file
View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2022 Signal Messenger, LLC
~ SPDX-License-Identifier: AGPL-3.0-only
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>TextSecureServer</artifactId>
<groupId>org.whispersystems.textsecure</groupId>
<version>JGITVER</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>event-logger</artifactId>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-logging</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-serialization-json</artifactId>
<version>${kotlinx-serialization.version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<compilerPlugins>
<plugin>kotlinx-serialization</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-serialization</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,14 @@
/*
* Copyright 2022 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.event
import java.util.Collections
import kotlinx.serialization.Serializable
sealed interface Event
@Serializable
data class RemoteConfigSetEvent(val token: String, val name: String, val percentage: Int, val defaultValue: String? = null, val value: String? = null, val hashKey: String? = null, val uuids: Collection<String> = Collections.emptyList()) : Event

View File

@ -0,0 +1,15 @@
/*
* Copyright 2022 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.event
interface Logger {
fun logEvent(event: Event, labels: Map<String, String>?)
fun logEvent(event: Event) = logEvent(event, null)
}
class NoOpLogger : Logger {
override fun logEvent(event: Event, labels: Map<String, String>?) {}
}

View File

@ -35,6 +35,7 @@
</pluginRepositories> </pluginRepositories>
<modules> <modules>
<module>event-logger</module>
<module>redis-dispatch</module> <module>redis-dispatch</module>
<module>websocket-resources</module> <module>websocket-resources</module>
<module>service</module> <module>service</module>
@ -53,6 +54,8 @@
<jackson.version>2.13.3</jackson.version> <jackson.version>2.13.3</jackson.version>
<jaxb.version>2.3.1</jaxb.version> <jaxb.version>2.3.1</jaxb.version>
<jedis.version>2.9.0</jedis.version> <jedis.version>2.9.0</jedis.version>
<kotlin.version>1.7.10</kotlin.version>
<kotlinx-serialization.version>1.4.0</kotlinx-serialization.version>
<lettuce.version>6.1.9.RELEASE</lettuce.version> <lettuce.version>6.1.9.RELEASE</lettuce.version>
<libphonenumber.version>8.12.54</libphonenumber.version> <libphonenumber.version>8.12.54</libphonenumber.version>
<logstash.logback.version>7.0.1</logstash.logback.version> <logstash.logback.version>7.0.1</logstash.logback.version>

View File

@ -24,6 +24,11 @@
<artifactId>jakarta.ws.rs-api</artifactId> <artifactId>jakarta.ws.rs-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.whispersystems.textsecure</groupId>
<artifactId>event-logger</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.whispersystems.textsecure</groupId> <groupId>org.whispersystems.textsecure</groupId>
<artifactId>redis-dispatch</artifactId> <artifactId>redis-dispatch</artifactId>

View File

@ -55,6 +55,7 @@ import javax.servlet.FilterRegistration;
import javax.servlet.ServletRegistration; import javax.servlet.ServletRegistration;
import org.eclipse.jetty.servlets.CrossOriginFilter; import org.eclipse.jetty.servlets.CrossOriginFilter;
import org.glassfish.jersey.server.ServerProperties; import org.glassfish.jersey.server.ServerProperties;
import org.signal.event.NoOpLogger;
import org.signal.i18n.HeaderControlledResourceBundleLookup; import org.signal.i18n.HeaderControlledResourceBundleLookup;
import org.signal.libsignal.zkgroup.ServerSecretParams; import org.signal.libsignal.zkgroup.ServerSecretParams;
import org.signal.libsignal.zkgroup.auth.ServerZkAuthOperations; import org.signal.libsignal.zkgroup.auth.ServerZkAuthOperations;
@ -644,7 +645,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
new PaymentsController(currencyManager, paymentsCredentialsGenerator), new PaymentsController(currencyManager, paymentsCredentialsGenerator),
new ProfileController(clock, rateLimiters, accountsManager, profilesManager, dynamicConfigurationManager, profileBadgeConverter, config.getBadges(), cdnS3Client, profileCdnPolicyGenerator, profileCdnPolicySigner, config.getCdnConfiguration().getBucket(), zkProfileOperations, batchIdentityCheckExecutor), new ProfileController(clock, rateLimiters, accountsManager, profilesManager, dynamicConfigurationManager, profileBadgeConverter, config.getBadges(), cdnS3Client, profileCdnPolicyGenerator, profileCdnPolicySigner, config.getCdnConfiguration().getBucket(), zkProfileOperations, batchIdentityCheckExecutor),
new ProvisioningController(rateLimiters, provisioningManager), new ProvisioningController(rateLimiters, provisioningManager),
new RemoteConfigController(remoteConfigsManager, config.getRemoteConfigConfiguration().getAuthorizedTokens(), config.getRemoteConfigConfiguration().getGlobalConfig()), new RemoteConfigController(remoteConfigsManager, new NoOpLogger(), config.getRemoteConfigConfiguration().getAuthorizedTokens(), config.getRemoteConfigConfiguration().getGlobalConfig()),
new SecureBackupController(backupCredentialsGenerator), new SecureBackupController(backupCredentialsGenerator),
new SecureStorageController(storageCredentialsGenerator), new SecureStorageController(storageCredentialsGenerator),
new StickerController(rateLimiters, config.getCdnConfiguration().getAccessKey(), new StickerController(rateLimiters, config.getCdnConfiguration().getAccessKey(),

View File

@ -14,6 +14,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -31,6 +32,8 @@ import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import org.signal.event.Logger;
import org.signal.event.RemoteConfigSetEvent;
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
import org.whispersystems.textsecuregcm.entities.UserRemoteConfig; import org.whispersystems.textsecuregcm.entities.UserRemoteConfig;
import org.whispersystems.textsecuregcm.entities.UserRemoteConfigList; import org.whispersystems.textsecuregcm.entities.UserRemoteConfigList;
@ -42,13 +45,15 @@ import org.whispersystems.textsecuregcm.util.Conversions;
public class RemoteConfigController { public class RemoteConfigController {
private final RemoteConfigsManager remoteConfigsManager; private final RemoteConfigsManager remoteConfigsManager;
private final List<String> configAuthTokens; private final Logger eventLogger;
private final Map<String, String> globalConfig; private final List<String> configAuthTokens;
private final Map<String, String> globalConfig;
private static final String GLOBAL_CONFIG_PREFIX = "global."; private static final String GLOBAL_CONFIG_PREFIX = "global.";
public RemoteConfigController(RemoteConfigsManager remoteConfigsManager, List<String> configAuthTokens, Map<String, String> globalConfig) { public RemoteConfigController(RemoteConfigsManager remoteConfigsManager, Logger eventLogger, List<String> configAuthTokens, Map<String, String> globalConfig) {
this.remoteConfigsManager = remoteConfigsManager; this.remoteConfigsManager = remoteConfigsManager;
this.eventLogger = Objects.requireNonNull(eventLogger);
this.configAuthTokens = configAuthTokens; this.configAuthTokens = configAuthTokens;
this.globalConfig = globalConfig; this.globalConfig = globalConfig;
} }
@ -88,6 +93,15 @@ public class RemoteConfigController {
throw new WebApplicationException(Response.Status.FORBIDDEN); throw new WebApplicationException(Response.Status.FORBIDDEN);
} }
eventLogger.logEvent(
new RemoteConfigSetEvent(
configToken,
config.getName(),
config.getPercentage(),
config.getDefaultValue(),
config.getValue(),
config.getHashKey(),
config.getUuids().stream().map(UUID::toString).collect(Collectors.toList())));
remoteConfigsManager.set(config); remoteConfigsManager.set(config);
} }

View File

@ -35,6 +35,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.signal.event.NoOpLogger;
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount;
import org.whispersystems.textsecuregcm.controllers.RemoteConfigController; import org.whispersystems.textsecuregcm.controllers.RemoteConfigController;
@ -57,7 +58,7 @@ class RemoteConfigControllerTest {
ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class)))
.setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory())
.addProvider(new DeviceLimitExceededExceptionMapper()) .addProvider(new DeviceLimitExceededExceptionMapper())
.addResource(new RemoteConfigController(remoteConfigsManager, remoteConfigsAuth, Map.of("maxGroupSize", "42"))) .addResource(new RemoteConfigController(remoteConfigsManager, new NoOpLogger(), remoteConfigsAuth, Map.of("maxGroupSize", "42")))
.build(); .build();