From 01f236a44f94e95506218eb3bc81fdee9ac56aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Pluta?= Date: Fri, 29 Mar 2019 23:02:28 +0100 Subject: [PATCH 1/3] 2: Create basic options and method dispatcher --- src/main/java/com/bartek/esa/EsaMain.java | 16 +++++++- .../bartek/esa/cli/model/CliArgsActions.java | 9 ----- .../bartek/esa/cli/model/CliArgsOptions.java | 19 ++++++++++ .../bartek/esa/cli/parser/CliArgsParser.java | 38 ++++++++++++++++++- .../com/bartek/esa/di/DependencyInjector.java | 4 +- .../esa/dispatcher/di/DispatcherModule.java | 14 +++++++ .../dispatcher/MethodDispatcher.java | 25 ++++++++++++ .../dispatcher/model/DispatcherActions.java | 13 +++++++ 8 files changed, 124 insertions(+), 14 deletions(-) delete mode 100644 src/main/java/com/bartek/esa/cli/model/CliArgsActions.java create mode 100644 src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java create mode 100644 src/main/java/com/bartek/esa/dispatcher/di/DispatcherModule.java create mode 100644 src/main/java/com/bartek/esa/dispatcher/dispatcher/MethodDispatcher.java create mode 100644 src/main/java/com/bartek/esa/dispatcher/model/DispatcherActions.java diff --git a/src/main/java/com/bartek/esa/EsaMain.java b/src/main/java/com/bartek/esa/EsaMain.java index f2845ac..4c179bc 100644 --- a/src/main/java/com/bartek/esa/EsaMain.java +++ b/src/main/java/com/bartek/esa/EsaMain.java @@ -1,5 +1,8 @@ package com.bartek.esa; +import com.bartek.esa.cli.model.CliArgsOptions; +import com.bartek.esa.dispatcher.dispatcher.MethodDispatcher; +import com.bartek.esa.dispatcher.model.DispatcherActions; import com.bartek.esa.cli.parser.CliArgsParser; import com.bartek.esa.di.DaggerDependencyInjector; @@ -7,14 +10,23 @@ import javax.inject.Inject; public class EsaMain { private final CliArgsParser cliArgsParser; + private final MethodDispatcher methodDispatcher; @Inject - EsaMain(CliArgsParser cliArgsParser) { + EsaMain(CliArgsParser cliArgsParser, MethodDispatcher methodDispatcher) { this.cliArgsParser = cliArgsParser; + this.methodDispatcher = methodDispatcher; } private void run(String[] args) { - // cliArgsParser.parse(...) + DispatcherActions dispatcherActions = DispatcherActions.builder() + .sourceAnalysis(source -> {}) + .apkAudit(source -> {}) + .build(); + + CliArgsOptions options = cliArgsParser.parse(args); + + methodDispatcher.dispatchMethod(options, dispatcherActions); } public static void main(String[] args) { diff --git a/src/main/java/com/bartek/esa/cli/model/CliArgsActions.java b/src/main/java/com/bartek/esa/cli/model/CliArgsActions.java deleted file mode 100644 index 313e601..0000000 --- a/src/main/java/com/bartek/esa/cli/model/CliArgsActions.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.bartek.esa.cli.model; - -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class CliArgsActions { -} diff --git a/src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java b/src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java new file mode 100644 index 0000000..fe6ca79 --- /dev/null +++ b/src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java @@ -0,0 +1,19 @@ +package com.bartek.esa.cli.model; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class CliArgsOptions { + private String sourceAnalysisDirectory; + private String apkAuditFile; + + public boolean isSourceAnalysis() { + return sourceAnalysisDirectory != null; + } + + public boolean isApkAudit() { + return apkAuditFile != null; + } +} diff --git a/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java b/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java index ec96d01..2c86e8e 100644 --- a/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java +++ b/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java @@ -1,15 +1,49 @@ package com.bartek.esa.cli.parser; -import com.bartek.esa.cli.model.CliArgsActions; +import com.bartek.esa.cli.model.CliArgsOptions; +import com.bartek.esa.error.EsaException; +import io.vavr.control.Try; +import org.apache.commons.cli.*; import javax.inject.Inject; public class CliArgsParser { + private static final String SRC_OPT = "src"; + private static final String APK_OPT = "apk"; @Inject public CliArgsParser() {} - public void parse(String[] args, CliArgsActions actions) { + public CliArgsOptions parse(String[] args) { + CommandLine command = Try.of(() -> new DefaultParser().parse(prepareOptions(), args)) + .getOrElseThrow(EsaException::new); + return CliArgsOptions.builder() + .sourceAnalysisDirectory(command.hasOption(SRC_OPT) ? command.getOptionValue(SRC_OPT) : null) + .apkAuditFile(command.hasOption(APK_OPT) ? command.getOptionValue(APK_OPT) : null) + .build(); + } + + private Options prepareOptions() { + Options options = new Options(); + options.addOption(source()); + options.addOption(apk()); + return options; + } + + private Option source() { + return Option.builder() + .longOpt(SRC_OPT) + .hasArg() + .desc("perform analysis for Java code and XML resources") + .build(); + } + + private Option apk() { + return Option.builder() + .longOpt(APK_OPT) + .hasArg() + .desc("perform audit for compiled APK file") + .build(); } } diff --git a/src/main/java/com/bartek/esa/di/DependencyInjector.java b/src/main/java/com/bartek/esa/di/DependencyInjector.java index 85d0744..0a601fb 100644 --- a/src/main/java/com/bartek/esa/di/DependencyInjector.java +++ b/src/main/java/com/bartek/esa/di/DependencyInjector.java @@ -2,10 +2,12 @@ package com.bartek.esa.di; import com.bartek.esa.EsaMain; import com.bartek.esa.cli.di.CliModule; +import com.bartek.esa.dispatcher.di.DispatcherModule; import dagger.Component; @Component(modules = { - CliModule.class + CliModule.class, + DispatcherModule.class }) public interface DependencyInjector { EsaMain esa(); diff --git a/src/main/java/com/bartek/esa/dispatcher/di/DispatcherModule.java b/src/main/java/com/bartek/esa/dispatcher/di/DispatcherModule.java new file mode 100644 index 0000000..88fe190 --- /dev/null +++ b/src/main/java/com/bartek/esa/dispatcher/di/DispatcherModule.java @@ -0,0 +1,14 @@ +package com.bartek.esa.dispatcher.di; + +import com.bartek.esa.dispatcher.dispatcher.MethodDispatcher; +import dagger.Module; +import dagger.Provides; + +@Module +public class DispatcherModule { + + @Provides + MethodDispatcher methodDispatcher() { + return new MethodDispatcher(); + } +} diff --git a/src/main/java/com/bartek/esa/dispatcher/dispatcher/MethodDispatcher.java b/src/main/java/com/bartek/esa/dispatcher/dispatcher/MethodDispatcher.java new file mode 100644 index 0000000..306795d --- /dev/null +++ b/src/main/java/com/bartek/esa/dispatcher/dispatcher/MethodDispatcher.java @@ -0,0 +1,25 @@ +package com.bartek.esa.dispatcher.dispatcher; + +import com.bartek.esa.cli.model.CliArgsOptions; +import com.bartek.esa.dispatcher.model.DispatcherActions; + +import javax.inject.Inject; + +public class MethodDispatcher { + + @Inject + public MethodDispatcher() { + + } + + public void dispatchMethod(CliArgsOptions options, DispatcherActions actions) { + if(options.isSourceAnalysis()) { + actions.getSourceAnalysis().accept(options.getSourceAnalysisDirectory()); + return; + } + + if(options.isApkAudit()) { + actions.getApkAudit().accept(options.getApkAuditFile()); + } + } +} diff --git a/src/main/java/com/bartek/esa/dispatcher/model/DispatcherActions.java b/src/main/java/com/bartek/esa/dispatcher/model/DispatcherActions.java new file mode 100644 index 0000000..a3411c8 --- /dev/null +++ b/src/main/java/com/bartek/esa/dispatcher/model/DispatcherActions.java @@ -0,0 +1,13 @@ +package com.bartek.esa.dispatcher.model; + +import lombok.Builder; +import lombok.Data; + +import java.util.function.Consumer; + +@Data +@Builder +public class DispatcherActions { + private Consumer sourceAnalysis; + private Consumer apkAudit; +} From 5b90131e024e5a610e7d9df57e8ad0895d441e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Pluta?= Date: Sat, 30 Mar 2019 09:49:33 +0100 Subject: [PATCH 2/3] 2: Add --exclude option and --help --- src/main/java/com/bartek/esa/EsaMain.java | 4 +- .../bartek/esa/cli/model/CliArgsOptions.java | 12 ++++ .../bartek/esa/cli/parser/CliArgsParser.java | 61 ++++++++++++++++--- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/bartek/esa/EsaMain.java b/src/main/java/com/bartek/esa/EsaMain.java index 4c179bc..781496d 100644 --- a/src/main/java/com/bartek/esa/EsaMain.java +++ b/src/main/java/com/bartek/esa/EsaMain.java @@ -1,10 +1,10 @@ package com.bartek.esa; import com.bartek.esa.cli.model.CliArgsOptions; -import com.bartek.esa.dispatcher.dispatcher.MethodDispatcher; -import com.bartek.esa.dispatcher.model.DispatcherActions; import com.bartek.esa.cli.parser.CliArgsParser; import com.bartek.esa.di.DaggerDependencyInjector; +import com.bartek.esa.dispatcher.dispatcher.MethodDispatcher; +import com.bartek.esa.dispatcher.model.DispatcherActions; import javax.inject.Inject; diff --git a/src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java b/src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java index fe6ca79..23f0b77 100644 --- a/src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java +++ b/src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java @@ -3,11 +3,15 @@ package com.bartek.esa.cli.model; import lombok.Builder; import lombok.Data; +import java.util.Collections; +import java.util.List; + @Data @Builder public class CliArgsOptions { private String sourceAnalysisDirectory; private String apkAuditFile; + private List excludes; public boolean isSourceAnalysis() { return sourceAnalysisDirectory != null; @@ -16,4 +20,12 @@ public class CliArgsOptions { public boolean isApkAudit() { return apkAuditFile != null; } + + public static CliArgsOptions empty() { + return CliArgsOptions.builder() + .sourceAnalysisDirectory(null) + .apkAuditFile(null) + .excludes(Collections.emptyList()) + .build(); + } } diff --git a/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java b/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java index 2c86e8e..13641e7 100644 --- a/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java +++ b/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java @@ -1,39 +1,66 @@ package com.bartek.esa.cli.parser; import com.bartek.esa.cli.model.CliArgsOptions; -import com.bartek.esa.error.EsaException; -import io.vavr.control.Try; import org.apache.commons.cli.*; import javax.inject.Inject; +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; + public class CliArgsParser { private static final String SRC_OPT = "src"; private static final String APK_OPT = "apk"; + private static final String EXCLUDE_OPT = "exclude"; + private static final String HELP_OPT = "help"; @Inject public CliArgsParser() {} public CliArgsOptions parse(String[] args) { - CommandLine command = Try.of(() -> new DefaultParser().parse(prepareOptions(), args)) - .getOrElseThrow(EsaException::new); + try { + CommandLine command = new DefaultParser().parse(prepareOptions(), args); - return CliArgsOptions.builder() - .sourceAnalysisDirectory(command.hasOption(SRC_OPT) ? command.getOptionValue(SRC_OPT) : null) - .apkAuditFile(command.hasOption(APK_OPT) ? command.getOptionValue(APK_OPT) : null) - .build(); + if (command.hasOption(HELP_OPT)) { + printHelp(); + return CliArgsOptions.empty(); + } + + boolean isNeitherAuditNorAnalysis = !command.hasOption(SRC_OPT) && !command.hasOption(APK_OPT); + if (isNeitherAuditNorAnalysis) { + printHelp(); + return CliArgsOptions.empty(); + } + + return CliArgsOptions.builder() + .sourceAnalysisDirectory(command.hasOption(SRC_OPT) ? command.getOptionValue(SRC_OPT) : null) + .apkAuditFile(command.hasOption(APK_OPT) ? command.getOptionValue(APK_OPT) : null) + .excludes(command.hasOption(EXCLUDE_OPT) ? asList(command.getOptionValues(EXCLUDE_OPT)) : emptyList()) + .build(); + } catch (ParseException e) { + printHelp(); + return CliArgsOptions.empty(); + } + } + + private void printHelp() { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp("esa", prepareOptions(), true); } private Options prepareOptions() { Options options = new Options(); options.addOption(source()); options.addOption(apk()); + options.addOption(exclude()); + options.addOption(help()); return options; } private Option source() { return Option.builder() .longOpt(SRC_OPT) + .argName("SOURCE_PATH") .hasArg() .desc("perform analysis for Java code and XML resources") .build(); @@ -42,8 +69,26 @@ public class CliArgsParser { private Option apk() { return Option.builder() .longOpt(APK_OPT) + .argName("APK_PATH") .hasArg() .desc("perform audit for compiled APK file") .build(); } + + private Option exclude() { + return Option.builder() + .longOpt(EXCLUDE_OPT) + .argName("CODES") + .numberOfArgs(Option.UNLIMITED_VALUES) + .desc("exclude particular security checks from audit/analysis") + .build(); + } + + private Option help() { + return Option.builder() + .longOpt(HELP_OPT) + .argName("h") + .desc("print this help") + .build(); + } } From c24d2f3e53fa0840df7f48483cdf73fa79fe24f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Pluta?= Date: Sat, 30 Mar 2019 10:44:19 +0100 Subject: [PATCH 3/3] 2: Add --plugins options --- .../bartek/esa/cli/model/CliArgsOptions.java | 11 ++-- .../bartek/esa/cli/parser/CliArgsParser.java | 56 ++++++++++++------- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java b/src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java index 23f0b77..ddcb5a9 100644 --- a/src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java +++ b/src/main/java/com/bartek/esa/cli/model/CliArgsOptions.java @@ -3,15 +3,17 @@ package com.bartek.esa.cli.model; import lombok.Builder; import lombok.Data; -import java.util.Collections; -import java.util.List; +import java.util.Set; + +import static java.util.Collections.emptySet; @Data @Builder public class CliArgsOptions { private String sourceAnalysisDirectory; private String apkAuditFile; - private List excludes; + private Set excludes; + private Set plugins; public boolean isSourceAnalysis() { return sourceAnalysisDirectory != null; @@ -25,7 +27,8 @@ public class CliArgsOptions { return CliArgsOptions.builder() .sourceAnalysisDirectory(null) .apkAuditFile(null) - .excludes(Collections.emptyList()) + .excludes(emptySet()) + .plugins(emptySet()) .build(); } } diff --git a/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java b/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java index 13641e7..dd23a4d 100644 --- a/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java +++ b/src/main/java/com/bartek/esa/cli/parser/CliArgsParser.java @@ -4,45 +4,52 @@ import com.bartek.esa.cli.model.CliArgsOptions; import org.apache.commons.cli.*; import javax.inject.Inject; +import java.util.HashSet; import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; +import static java.util.Collections.emptySet; public class CliArgsParser { private static final String SRC_OPT = "src"; private static final String APK_OPT = "apk"; private static final String EXCLUDE_OPT = "exclude"; private static final String HELP_OPT = "help"; + private static final String PLUGINS_OPT = "plugins"; @Inject public CliArgsParser() {} public CliArgsOptions parse(String[] args) { try { - CommandLine command = new DefaultParser().parse(prepareOptions(), args); - - if (command.hasOption(HELP_OPT)) { - printHelp(); - return CliArgsOptions.empty(); - } - - boolean isNeitherAuditNorAnalysis = !command.hasOption(SRC_OPT) && !command.hasOption(APK_OPT); - if (isNeitherAuditNorAnalysis) { - printHelp(); - return CliArgsOptions.empty(); - } - - return CliArgsOptions.builder() - .sourceAnalysisDirectory(command.hasOption(SRC_OPT) ? command.getOptionValue(SRC_OPT) : null) - .apkAuditFile(command.hasOption(APK_OPT) ? command.getOptionValue(APK_OPT) : null) - .excludes(command.hasOption(EXCLUDE_OPT) ? asList(command.getOptionValues(EXCLUDE_OPT)) : emptyList()) - .build(); + return tryToParse(args); } catch (ParseException e) { printHelp(); return CliArgsOptions.empty(); } } + private CliArgsOptions tryToParse(String[] args) throws ParseException { + CommandLine command = new DefaultParser().parse(prepareOptions(), args); + + if (command.hasOption(HELP_OPT)) { + printHelp(); + return CliArgsOptions.empty(); + } + + boolean isNeitherAuditNorAnalysis = !command.hasOption(SRC_OPT) && !command.hasOption(APK_OPT); + if (isNeitherAuditNorAnalysis) { + printHelp(); + return CliArgsOptions.empty(); + } + + return CliArgsOptions.builder() + .sourceAnalysisDirectory(command.hasOption(SRC_OPT) ? command.getOptionValue(SRC_OPT) : null) + .apkAuditFile(command.hasOption(APK_OPT) ? command.getOptionValue(APK_OPT) : null) + .plugins(command.hasOption(PLUGINS_OPT) ? new HashSet<>(asList(command.getOptionValues(PLUGINS_OPT))) : emptySet()) + .excludes(command.hasOption(EXCLUDE_OPT) ? new HashSet<>(asList(command.getOptionValues(EXCLUDE_OPT))) : emptySet()) + .build(); + } + private void printHelp() { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp("esa", prepareOptions(), true); @@ -53,6 +60,7 @@ public class CliArgsParser { options.addOption(source()); options.addOption(apk()); options.addOption(exclude()); + options.addOption(plugins()); options.addOption(help()); return options; } @@ -87,8 +95,16 @@ public class CliArgsParser { private Option help() { return Option.builder() .longOpt(HELP_OPT) - .argName("h") .desc("print this help") .build(); } + + private Option plugins() { + return Option.builder() + .longOpt(PLUGINS_OPT) + .argName("CODES") + .numberOfArgs(Option.UNLIMITED_VALUES) + .desc("use only selected security checks for audit/analysis") + .build(); + } }