🤬
  • Connect java Tsunami workflow with python grpc server and update gRPC deadline time on the Java client side.

    PiperOrigin-RevId: 466781143
    Change-Id: I7da50e3c0fab2704dab956fa7bdc725e288e7a2e
  • Loading...
  • John Y. Kim committed with Copybara-Service 2 years ago
    67bb43e5
    1 parent 3620e0ac
  • ■ ■ ■ ■ ■
    build.gradle
    skipped 66 lines
    67 67   grpc_core: "io.grpc:grpc-core:${grpcVersion}",
    68 68   grpc_services: "io.grpc:grpc-services:${grpcVersion}",
    69 69   grpc_testing: "io.grpc:grpc-testing:${grpcVersion}",
     70 + grpc_netty: "io.grpc:grpc-netty:${grpcVersion}",
    70 71   javax_annotations: "javax.annotation:javax.annotation-api:${javaxAnnotationVersion}",
    71 72   gson: "com.google.code.gson:gson:${gsonVersion}",
    72 73   jaxb_runtime: "org.glassfish.jaxb:jaxb-runtime:${jaxbVersion}",
    skipped 154 lines
  • ■ ■ ■ ■
    main/src/main/java/com/google/tsunami/main/cli/server/ServerPortCommand.java common/src/main/java/com/google/tsunami/common/server/ServerPortCommand.java
    skipped 12 lines
    13 13   * See the License for the specific language governing permissions and
    14 14   * limitations under the License.
    15 15   */
    16  -package com.google.tsunami.main.cli.server;
     16 +package com.google.tsunami.common.server;
    17 17   
    18 18  import com.google.auto.value.AutoValue;
    19 19   
    skipped 12 lines
  • ■ ■ ■ ■ ■
    main/build.gradle
    skipped 13 lines
    14 14   compile deps.flogger_google_ext
    15 15   compile deps.guava
    16 16   compile deps.jsoup
    17  - compile deps.autovalue
     17 + compile deps.grpc_netty
    18 18   runtime deps.jaxb_runtime
    19  - annotationProcessor deps.autovalue_annotation_processor
    20 19   
    21 20   testCompile deps.junit
    22 21   testCompile deps.mockito
    skipped 12 lines
  • ■ ■ ■ ■ ■ ■
    main/src/main/java/com/google/tsunami/main/cli/LanguageServerOptions.java
    skipped 55 lines
    56 56   if (pluginServerPorts != null && !pluginServerPorts.isEmpty()) {
    57 57   for (String pluginServerPort : pluginServerPorts) {
    58 58   try {
    59  - var port = Integer.parseInt(pluginServerPort);
     59 + var port = Integer.parseInt(pluginServerPort, 10);
    60 60   if (!(port <= NetworkEndpointUtils.MAX_PORT_NUMBER && port > 0)) {
    61 61   throw new ParameterException(
    62 62   String.format(
    skipped 8 lines
    71 71   }
    72 72   }
    73 73   
    74  - if ((pluginServerFilenames != null && pluginServerPorts == null)
    75  - || (pluginServerFilenames == null && pluginServerPorts != null)
    76  - || (pluginServerFilenames.size() != pluginServerPorts.size())) {
     74 + var pathCounts = pluginServerFilenames == null ? 0 : pluginServerFilenames.size();
     75 + var portCounts = pluginServerPorts == null ? 0 : pluginServerPorts.size();
     76 + if (pathCounts != portCounts) {
    77 77   throw new ParameterException(
    78 78   String.format(
    79 79   "Number of plugin server paths must be equal to number of plugin server ports."
    80 80   + " Paths: %s. Ports: %s.",
    81  - pluginServerFilenames.size(), pluginServerPorts.size()));
     81 + pathCounts, portCounts));
    82 82   }
    83 83   }
    84 84   }
    skipped 2 lines
  • ■ ■ ■ ■ ■ ■
    main/src/main/java/com/google/tsunami/main/cli/TsunamiCli.java
    skipped 22 lines
    23 23   
    24 24  import com.google.common.base.Splitter;
    25 25  import com.google.common.base.Stopwatch;
     26 +import com.google.common.collect.ImmutableList;
    26 27  import com.google.common.collect.Iterables;
     28 +import com.google.common.collect.Lists;
    27 29  import com.google.common.flogger.GoogleLogger;
    28 30  import com.google.inject.AbstractModule;
    29 31  import com.google.inject.Guice;
    skipped 7 lines
    37 39  import com.google.tsunami.common.io.archiving.GoogleCloudStorageArchiverModule;
    38 40  import com.google.tsunami.common.net.http.HttpClientModule;
    39 41  import com.google.tsunami.common.reflection.ClassGraphModule;
     42 +import com.google.tsunami.common.server.ServerPortCommand;
    40 43  import com.google.tsunami.common.time.SystemUtcClockModule;
    41 44  import com.google.tsunami.main.cli.option.MainCliOptions;
     45 +import com.google.tsunami.main.cli.server.RemoteServerLoader;
     46 +import com.google.tsunami.main.cli.server.RemoteServerLoaderModule;
    42 47  import com.google.tsunami.plugin.PluginExecutionModule;
    43 48  import com.google.tsunami.plugin.PluginLoadingModule;
     49 +import com.google.tsunami.plugin.RemoteVulnDetectorLoadingModule;
    44 50  import com.google.tsunami.plugin.payload.PayloadGeneratorModule;
    45 51  import com.google.tsunami.proto.ScanResults;
    46 52  import com.google.tsunami.proto.ScanStatus;
    skipped 4 lines
    51 57  import io.github.classgraph.ScanResult;
    52 58  import java.io.IOException;
    53 59  import java.security.SecureRandom;
     60 +import java.util.List;
    54 61  import java.util.Optional;
    55 62  import java.util.concurrent.ExecutionException;
    56 63  import javax.inject.Inject;
    skipped 5 lines
    62 69   private final DefaultScanningWorkflow scanningWorkflow;
    63 70   private final ScanResultsArchiver scanResultsArchiver;
    64 71   private final MainCliOptions mainCliOptions;
     72 + private final RemoteServerLoader remoteServerLoader;
    65 73   
    66 74   @Inject
    67 75   TsunamiCli(
    68 76   DefaultScanningWorkflow scanningWorkflow,
    69 77   ScanResultsArchiver scanResultsArchiver,
    70  - MainCliOptions mainCliOptions) {
     78 + MainCliOptions mainCliOptions,
     79 + RemoteServerLoader remoteServerLoader) {
    71 80   this.scanningWorkflow = checkNotNull(scanningWorkflow);
    72 81   this.scanResultsArchiver = checkNotNull(scanResultsArchiver);
    73 82   this.mainCliOptions = checkNotNull(mainCliOptions);
     83 + this.remoteServerLoader = checkNotNull(remoteServerLoader);
    74 84   }
    75 85   
    76 86   public boolean run()
    skipped 1 lines
    78 88   String logId = (mainCliOptions.logId == null) ? "" : (mainCliOptions.logId + ": ");
    79 89   // TODO(b/171405612): Find a way to print the log ID at every log line.
    80 90   logger.atInfo().log("%sTsunamiCli starting...", logId);
     91 + 
     92 + ImmutableList<Process> languageServerProcesses = remoteServerLoader.runServerProcesses();
    81 93   ScanResults scanResults = scanningWorkflow.run(buildScanTarget());
     94 + languageServerProcesses.forEach(Process::destroy);
    82 95   
    83 96   logger.atInfo().log("Tsunami scan finished, saving results.");
    84 97   saveResults(scanResults);
    skipped 54 lines
    139 152   protected void configure() {
    140 153   // TODO(b/171405612): Find a way to use the log ID extracted by the CLI options.
    141 154   String logId = extractLogId(args);
     155 + 
     156 + // TODO(b/241964583): Only use LanguageServerOptions to extract language server args.
     157 + ImmutableList<ServerPortCommand> commands = extractPluginServerArgs(args);
     158 + 
    142 159   install(new ClassGraphModule(classScanResult));
    143 160   install(new ConfigModule(classScanResult, tsunamiConfig));
    144 161   install(new CliOptionsModule(classScanResult, "TsunamiCli", args));
    skipped 5 lines
    150 167   install(new PluginExecutionModule());
    151 168   install(new PluginLoadingModule(classScanResult));
    152 169   install(new PayloadGeneratorModule(new SecureRandom()));
     170 + install(new RemoteServerLoaderModule(commands));
     171 + install(new RemoteVulnDetectorLoadingModule(commands));
     172 + }
     173 + 
     174 + private ImmutableList<ServerPortCommand> extractPluginServerArgs(String[] args) {
     175 + var paths = extractPluginServerPaths(args);
     176 + var ports = extractPluginServerPorts(args);
     177 + if (paths.size() == ports.size()) {
     178 + List<ServerPortCommand> commands = Lists.newArrayList();
     179 + for (int i = 0; i < paths.size(); ++i) {
     180 + commands.add(ServerPortCommand.create(paths.get(i), ports.get(i)));
     181 + }
     182 + return ImmutableList.copyOf(commands);
     183 + }
     184 + return ImmutableList.of();
     185 + }
     186 + 
     187 + private ImmutableList<String> extractPluginServerPaths(String[] args) {
     188 + for (int i = 0; i < args.length; ++i) {
     189 + if (args[i].startsWith("--plugin-server-paths=")) {
     190 + var paths = Iterables.get(Splitter.on('=').split(args[i]), 1);
     191 + return ImmutableList.copyOf(Splitter.on(',').split(paths));
     192 + }
     193 + }
     194 + return ImmutableList.of();
     195 + }
     196 + 
     197 + private ImmutableList<String> extractPluginServerPorts(String[] args) {
     198 + for (int i = 0; i < args.length; ++i) {
     199 + if (args[i].startsWith("--plugin-server-ports=")) {
     200 + var ports = Iterables.get(Splitter.on('=').split(args[i]), 1);
     201 + return ImmutableList.copyOf(Splitter.on(',').split(ports));
     202 + }
     203 + }
     204 + return ImmutableList.of();
    153 205   }
    154 206   
    155 207   private String extractLogId(String[] args) {
    skipped 26 lines
    182 234   if (!injector.getInstance(TsunamiCli.class).run()) {
    183 235   System.exit(1);
    184 236   }
    185  - 
    186 237   logger.atInfo().log("Full Tsunami scan took %s.", stopwatch.stop());
    187 238   } catch (Throwable e) {
    188 239   logger.atSevere().withCause(e).log("Exiting due to workflow execution exceptions.");
    skipped 30 lines
  • ■ ■ ■ ■ ■
    main/src/main/java/com/google/tsunami/main/cli/server/RemoteServerLoader.java
    skipped 22 lines
    23 23  import com.google.common.flogger.GoogleLogger;
    24 24  import com.google.tsunami.common.command.CommandExecutor;
    25 25  import com.google.tsunami.common.command.CommandExecutorFactory;
     26 +import com.google.tsunami.common.server.ServerPortCommand;
    26 27  import java.io.IOException;
    27 28  import java.lang.annotation.Retention;
    28 29  import java.util.List;
    skipped 14 lines
    43 44   }
    44 45   
    45 46   public ImmutableList<Process> runServerProcesses() {
    46  - logger.atInfo().log("Starting language server processes...");
     47 + logger.atInfo().log("Starting language server processes (if any)...");
    47 48   return commands.stream()
    48 49   .map(
    49 50   command ->
    skipped 23 lines
  • ■ ■ ■ ■ ■
    main/src/main/java/com/google/tsunami/main/cli/server/RemoteServerLoaderModule.java
    skipped 17 lines
    18 18  import com.google.common.collect.ImmutableList;
    19 19  import com.google.inject.AbstractModule;
    20 20  import com.google.inject.Provides;
     21 +import com.google.tsunami.common.server.ServerPortCommand;
    21 22  import java.util.List;
    22 23   
    23 24  /** Installs {@link RemoteServerLoaderModule}. */
    skipped 15 lines
  • ■ ■ ■ ■ ■
    main/src/test/java/com/google/tsunami/main/cli/server/RemoteServerLoaderTest.java
    skipped 19 lines
    20 20  import com.google.common.collect.ImmutableList;
    21 21  import com.google.inject.AbstractModule;
    22 22  import com.google.inject.Guice;
     23 +import com.google.tsunami.common.server.ServerPortCommand;
    23 24  import org.junit.Test;
    24 25  import org.junit.runner.RunWith;
    25 26  import org.junit.runners.JUnit4;
    skipped 23 lines
  • ■ ■ ■ ■ ■
    plugin/build.gradle
    skipped 14 lines
    15 15   compile deps.protobuf
    16 16   compile deps.protobuf_util
    17 17   compile deps.grpc_core
     18 + compile deps.grpc_netty
    18 19   compile deps.grpc_testing
    19 20   compile deps.grpc_context
    20 21   compile deps.grpc_services
    skipped 9 lines
  • ■ ■ ■ ■
    plugin/src/main/java/com/google/tsunami/plugin/RemoteVulnDetectorImpl.java
    skipped 37 lines
    38 38  final class RemoteVulnDetectorImpl implements RemoteVulnDetector {
    39 39   private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
    40 40   // Default duration deadline for all RPC calls
    41  - private static final Deadline DEFAULT_DEADLINE = Deadline.after(30, SECONDS);
     41 + private static final Deadline DEFAULT_DEADLINE = Deadline.after(120, SECONDS);
    42 42   
    43 43   private final PluginServiceClient service;
    44 44   private final Set<MatchedPlugin> pluginsToRun;
    skipped 59 lines
  • ■ ■ ■ ■ ■
    plugin/src/main/java/com/google/tsunami/plugin/RemoteVulnDetectorLoadingModule.java
    skipped 15 lines
    16 16  package com.google.tsunami.plugin;
    17 17   
    18 18  import static com.google.common.base.Preconditions.checkNotNull;
     19 +import static com.google.common.collect.ImmutableList.toImmutableList;
    19 20   
    20 21  import com.google.auto.value.AutoAnnotation;
    21 22  import com.google.auto.value.AutoBuilder;
    skipped 1 lines
    23 24  import com.google.common.collect.ImmutableList;
    24 25  import com.google.inject.AbstractModule;
    25 26  import com.google.inject.multibindings.MapBinder;
     27 +import com.google.tsunami.common.server.ServerPortCommand;
    26 28  import com.google.tsunami.plugin.annotations.PluginInfo;
    27 29  import io.grpc.Channel;
     30 +import io.grpc.netty.NegotiationType;
     31 +import io.grpc.netty.NettyChannelBuilder;
    28 32   
    29 33  /** A Guice module that loads all {@link RemoteVulnDetector RemoteVulnDetectors} at runtime. */
    30 34  public final class RemoteVulnDetectorLoadingModule extends AbstractModule {
     35 + private static final int MAX_MESSAGE_SIZE =
     36 + 10 * 1000 * 1000; // Max incoming gRPC message size 10MB.
    31 37   
    32  - private final ImmutableList<Channel> availableChannels;
     38 + private final ImmutableList<ServerPortCommand> availableServerPorts;
    33 39   
    34  - public RemoteVulnDetectorLoadingModule(ImmutableList<Channel> channels) {
    35  - this.availableChannels = checkNotNull(channels);
     40 + public RemoteVulnDetectorLoadingModule(ImmutableList<ServerPortCommand> serverPorts) {
     41 + this.availableServerPorts = checkNotNull(serverPorts);
    36 42   }
    37 43   
    38 44   @Override
    39 45   protected void configure() {
     46 + ImmutableList<Channel> availableChannels = getLanguageServerChannels(availableServerPorts);
    40 47   MapBinder<PluginDefinition, TsunamiPlugin> tsunamiPluginBinder =
    41 48   MapBinder.newMapBinder(binder(), PluginDefinition.class, TsunamiPlugin.class);
    42 49   availableChannels.forEach(
    skipped 1 lines
    44 51   tsunamiPluginBinder
    45 52   .addBinding(getRemoteVulnDetectorPluginDefinition(channel.hashCode()))
    46 53   .toInstance(new RemoteVulnDetectorImpl(channel)));
     54 + }
     55 + 
     56 + private ImmutableList<Channel> getLanguageServerChannels(
     57 + ImmutableList<ServerPortCommand> commands) {
     58 + return commands.stream()
     59 + .map(
     60 + command ->
     61 + NettyChannelBuilder.forTarget("localhost:" + command.port())
     62 + .negotiationType(NegotiationType.PLAINTEXT)
     63 + .maxInboundMessageSize(MAX_MESSAGE_SIZE)
     64 + .build())
     65 + .collect(toImmutableList());
    47 66   }
    48 67   
    49 68   // TODO(b/239095108): Change channelIds to something more meaningful to identify
    skipped 56 lines
  • ■ ■ ■ ■ ■
    plugin/src/test/java/com/google/tsunami/plugin/RemoteVulnDetectorLoadingModuleTest.java
    skipped 20 lines
    21 21  import com.google.inject.Guice;
    22 22  import com.google.inject.Key;
    23 23  import com.google.inject.util.Types;
    24  -import io.grpc.Channel;
    25  -import io.grpc.inprocess.InProcessChannelBuilder;
     24 +import com.google.tsunami.common.server.ServerPortCommand;
    26 25  import io.grpc.inprocess.InProcessServerBuilder;
    27 26  import java.util.Map;
    28 27  import org.junit.Test;
    skipped 12 lines
    41 40   return InProcessServerBuilder.generateName();
    42 41   }
    43 42   
    44  - private static Channel generateChannel(String serverName) {
    45  - return InProcessChannelBuilder.forName(serverName).directExecutor().build();
    46  - }
    47  - 
    48 43   @Test
    49 44   public void configure_whenNoChannelsRegistered_loadsNoRemotePlugins() {
    50 45   Map<PluginDefinition, TsunamiPlugin> remotePlugins =
    skipped 5 lines
    56 51   
    57 52   @Test
    58 53   public void configure_always_loadsAllRemotePlugins() {
    59  - var channelName0 = generateChannel(generateServerName());
    60  - var channelName1 = generateChannel(generateServerName());
     54 + var path0 = ServerPortCommand.create(generateServerName(), "34567");
     55 + var path1 = ServerPortCommand.create(generateServerName(), "34566");
    61 56   Map<PluginDefinition, TsunamiPlugin> remotePlugins =
    62 57   Guice.createInjector(
    63  - new RemoteVulnDetectorLoadingModule(ImmutableList.of(channelName0, channelName1)))
     58 + new RemoteVulnDetectorLoadingModule(ImmutableList.of(path0, path1)))
    64 59   .getInstance(PLUGIN_BINDING_KEY);
    65 60   
    66 61   assertThat(remotePlugins).hasSize(2);
    67  - assertThat(remotePlugins.keySet())
    68  - .containsExactly(
    69  - RemoteVulnDetectorLoadingModule.getRemoteVulnDetectorPluginDefinition(
    70  - channelName0.hashCode()),
    71  - RemoteVulnDetectorLoadingModule.getRemoteVulnDetectorPluginDefinition(
    72  - channelName1.hashCode()));
    73 62   }
    74 63  }
    75 64   
Please wait...
Page is in error, reload to recover