From 6b76d873e63fec38e82c8e2da3d19ca1b5ff1510 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Tue, 5 Mar 2024 00:49:32 -0500 Subject: [PATCH] Upgrade JCommander to support global argument validation. Replace CredentialArgumentValidator with CreateArgumentValidator. --- settings.gradle | 2 +- .../src/main/java/hirs/swid/Main.java | 15 +--- .../main/java/hirs/swid/utils/Commander.java | 18 ++-- .../swid/utils/CreateArgumentValidator.java | 82 +++++++++++++++++++ 4 files changed, 95 insertions(+), 22 deletions(-) create mode 100644 tools/tcg_rim_tool/src/main/java/hirs/swid/utils/CreateArgumentValidator.java diff --git a/settings.gradle b/settings.gradle index 44f38ec3..1d09049c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -25,7 +25,7 @@ dependencyResolutionManagement { library('jakarta-servlet', 'org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.0') library('jakarta-api', 'jakarta.persistence:jakarta.persistence-api:3.1.0') library('jakarta-xml', 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.0') - library('jcommander', 'com.beust:jcommander:1.82') + library('jcommander', 'org.jcommander:jcommander:1.83') library('hibernate-core', 'org.hibernate:hibernate-core:6.1.7.Final') library('jackson-core', 'com.fasterxml.jackson.core', 'jackson-core').versionRef('jackson') library('jackson-databind', 'com.fasterxml.jackson.core', 'jackson-databind').versionRef('jackson') diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index baa8412f..58870de7 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -28,7 +28,6 @@ public class Main { SwidTagGateway gateway; ReferenceManifestValidator validator; List unknownOpts = commander.getUnknownOptions(); - CredentialArgumentValidator credValidator; if (!unknownOpts.isEmpty()) { StringBuilder sb = new StringBuilder("Unknown options encountered: "); @@ -58,13 +57,7 @@ public class Main { String trustStore = commander.getTruststoreFile(); validator.setRim(verifyFile); validator.setRimEventLog(rimel); - credValidator = new CredentialArgumentValidator(trustStore, - "","", true); - if (credValidator.isValid()) { - validator.setTrustStoreFile(trustStore); - } else { - exitWithErrorCode(credValidator.getErrorMessage()); - } + validator.setTrustStoreFile(trustStore); if (validator.validateSwidtagFile(verifyFile)) { System.out.println("Successfully verified " + verifyFile); } else { @@ -86,20 +79,16 @@ public class Main { case "BASE": gateway.setAttributesFile(attributesFile); gateway.setRimEventLog(rimEventLog); - credValidator = new CredentialArgumentValidator("" , - certificateFile, privateKeyFile, false); if (defaultKey){ gateway.setDefaultCredentials(true); gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE); - } else if (credValidator.isValid()) { + } else { gateway.setDefaultCredentials(false); gateway.setPemCertificateFile(certificateFile); gateway.setPemPrivateKeyFile(privateKeyFile); if (embeddedCert) { gateway.setEmbeddedCert(true); } - } else { - exitWithErrorCode(credValidator.getErrorMessage()); } List timestampArguments = commander.getTimestampArguments(); if (timestampArguments.size() > 0) { diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java index b9630e17..f6851e2b 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java @@ -1,6 +1,7 @@ package hirs.swid.utils; import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; import hirs.swid.SwidTagConstants; import java.util.ArrayList; @@ -10,39 +11,40 @@ import java.util.List; * Commander is a class that handles the command line arguments for the SWID * Tags gateway by implementing the JCommander package. */ +@Parameters(parametersValidators = CreateArgumentValidator.class) public class Commander { @Parameter(description = "This parameter catches all unrecognized arguments.") private List unknownOptions = new ArrayList<>(); @Parameter(names = {"-h", "--help"}, help = true, description = "Print this help text.") private boolean help; - @Parameter(names = {"-c", "--create \"base\""}, order = 0, + @Parameter(names = {"-c", "--create"}, order = 0, description = "The type of RIM to create. A base RIM will be created by default.") private String createType = ""; - @Parameter(names = {"-v", "--verify "}, validateWith = FileArgumentValidator.class, + @Parameter(names = {"-v", "--verify"}, validateWith = FileArgumentValidator.class, description = "Specify a RIM file to verify.") private String verifyFile = ""; @Parameter(names = {"-V", "--version"}, description = "Output the current version.") private boolean version = false; - @Parameter(names = {"-a", "--attributes "}, validateWith = FileArgumentValidator.class, + @Parameter(names = {"-a", "--attributes"}, validateWith = FileArgumentValidator.class, description = "The configuration file holding attributes " + "to populate the base RIM with. An example file can be found in /opt/rimtool/data.") private String attributesFile = ""; - @Parameter(names = {"-o", "--out "}, order = 2, + @Parameter(names = {"-o", "--out"}, order = 2, description = "The file to write the RIM out to. " + "The RIM will be written to stdout by default.") private String outFile = ""; @Parameter(names = {"--verbose"}, description = "Control output verbosity.") private boolean verbose = false; - @Parameter(names = {"-t", "--truststore "}, validateWith = FileArgumentValidator.class, + @Parameter(names = {"-t", "--truststore"}, validateWith = FileArgumentValidator.class, description = "The truststore to sign the base RIM created " + "or to validate the signed base RIM.") private String truststoreFile = ""; - @Parameter(names = {"-k", "--privateKeyFile "}, + @Parameter(names = {"-k", "--privateKeyFile"}, validateWith = FileArgumentValidator.class, description = "The private key used to sign the base RIM created by this tool.") private String privateKeyFile = ""; - @Parameter(names = {"-p", "--publicCertificate "}, + @Parameter(names = {"-p", "--publicCertificate"}, validateWith = FileArgumentValidator.class, description = "The public key certificate to embed in the base RIM created by " + "this tool.") @@ -53,7 +55,7 @@ public class Commander { @Parameter(names = {"-d", "--default-key"}, order = 8, description = "Use the JKS keystore installed in /opt/rimtool/data.") private boolean defaultKey = false; - @Parameter(names = {"-l", "--rimel "}, validateWith = FileArgumentValidator.class, + @Parameter(names = {"-l", "--rimel"}, validateWith = FileArgumentValidator.class, description = "The TCG eventlog file to use as a support RIM.") private String rimEventLog = ""; @Parameter(names = {"--timestamp"}, order = 10, variableArity = true, diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/CreateArgumentValidator.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/CreateArgumentValidator.java new file mode 100644 index 00000000..2b47b413 --- /dev/null +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/CreateArgumentValidator.java @@ -0,0 +1,82 @@ +package hirs.swid.utils; + +import com.beust.jcommander.IParametersValidator; +import com.beust.jcommander.ParameterException; +import lombok.extern.log4j.Log4j2; + +import java.util.Map; + +/** + * This class handles validating all arguments in the context of a create+sign function. + * The input arguments are checked that --verify is not also selected and that all + * required inputs for --create are present. + */ +@Log4j2 +public class CreateArgumentValidator implements IParametersValidator { + String[] requiredArgs = {"--attributes", "--rimel"}; + String errorMessage = ""; + + /** + * This method validates the input parameter map. + * @param parameters + * Name-value-pairs of all parameters (e.g. "-host":"localhost"). + * + * @throws ParameterException + */ + @Override + public void validate(Map parameters) throws ParameterException { + if (isValueNotNull(parameters,"--create")) { + if (isValueNotNull(parameters,"--verify")) { + errorMessage += "Create and verify cannot be called together. "; + } else { + for (String arg : requiredArgs) { + if (!isValueNotNull(parameters, arg)) { + errorMessage += arg + " is required to create and sign a base RIM. "; + } + } + validateSigningCredentials(parameters); + } + } + if (!errorMessage.isEmpty()) { + throw new ParameterException(errorMessage); + } + } + + /** + * This method checks the given key for a null value + * @param parameters map + * @param key the key to check + * @return true if not null, else false + */ + private boolean isValueNotNull(Map parameters, String key) { + Object object = parameters.get(key); + if (object == null) { + return false; + } else { + return true; + } + } + + private void validateSigningCredentials(Map parameters) { + if (isValueNotNull(parameters, "--default-key") && + (isValueNotNull(parameters, "--privateKeyFile") || + isValueNotNull(parameters, "--publicCertificate"))) { + errorMessage += "Too many signing credentials given, either choose --default-key OR " + + "provide --privateKeyFile and --publicCertificate"; + } else if (!isValueNotNull(parameters, "--default-key") && + !isValueNotNull(parameters, "--privateKeyFile") && + !isValueNotNull(parameters, "--publicCertificate")) { + errorMessage += "No signing credentials given, either choose --default-key OR " + + "provide --privateKeyFile and --publicCertificate"; + } else { + if (!(isValueNotNull(parameters, "--privateKeyFile") && + isValueNotNull(parameters, "--publicCertificate"))) { + if (isValueNotNull(parameters, "--privateKeyFile")) { + errorMessage += "A signing certificate is missing. "; + } else { + errorMessage += "A private key is missing. "; + } + } + } + } +}