diff --git a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/cli/cmd/AbstractActionImportCommand.java b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/cli/cmd/AbstractActionImportCommand.java index 49a885bab7..52a24a8c48 100644 --- a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/cli/cmd/AbstractActionImportCommand.java +++ b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/cli/cmd/AbstractActionImportCommand.java @@ -19,6 +19,7 @@ import picocli.CommandLine.ArgGroup; import picocli.CommandLine.Option; +// TODO Re-implement import functionality public abstract class AbstractActionImportCommand extends AbstractOutputCommand implements IJsonNodeSupplier { @ArgGroup(exclusive = true, multiplicity = "1") private ImportArgGroup argGroup = new ImportArgGroup(); private static final class ImportArgGroup { diff --git a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/helper/ActionImportHelper.java b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/helper/ActionImportHelper.java index 44c0d6a1e0..962d489cb1 100644 --- a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/helper/ActionImportHelper.java +++ b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/helper/ActionImportHelper.java @@ -17,9 +17,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fortify.cli.common.action.helper.ActionLoaderHelper.ActionInvalidSignatureHandlers; import com.fortify.cli.common.action.helper.ActionLoaderHelper.ActionSource; -import com.fortify.cli.common.action.model.Action.ActionProperties; import com.fortify.cli.common.json.JsonHelper; -import com.fortify.cli.common.util.Break; import lombok.SneakyThrows; diff --git a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/helper/ActionLoaderHelper.java b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/helper/ActionLoaderHelper.java index 8bec8e2ab5..83d92ad35b 100644 --- a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/helper/ActionLoaderHelper.java +++ b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/helper/ActionLoaderHelper.java @@ -38,6 +38,7 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.fortify.cli.common.action.model.Action; import com.fortify.cli.common.action.model.Action.ActionProperties; +import com.fortify.cli.common.cli.mixin.CommonOptionMixins.RequireConfirmation.AbortedByUserException; import com.fortify.cli.common.crypto.SignatureHelper; import com.fortify.cli.common.crypto.SignatureHelper.InvalidSignatureHandler; import com.fortify.cli.common.crypto.SignatureHelper.SignatureStatus; @@ -121,7 +122,6 @@ public final void processActions(ActionLoadResultProcessor actionLoadResultProce processZipEntries(zipEntryProcessor(actionLoadResultProcessor)); } - @SneakyThrows private final ActionLoadResult loadFromFileOrUrl(String source) { try ( var is = createSourceInputStream(source, false) ) { if ( is!=null ) { @@ -129,14 +129,21 @@ private final ActionLoadResult loadFromFileOrUrl(String source) { .custom(true).name(source).build(); return load(is, properties); } + } catch (Exception e) { + if ( e instanceof AbortedByUserException ) { throw (AbortedByUserException)e; } + throw wrapException("Error loading action from "+source, e); } return null; } private final ActionLoadResult loadFromZips(String name) { - AtomicReference result = new AtomicReference<>(); - processZipEntries(singleZipEntryProcessor(name, result::set)); - return result.get(); + try { + AtomicReference result = new AtomicReference<>(); + processZipEntries(singleZipEntryProcessor(name, result::set)); + return result.get(); + } catch ( RuntimeException e ) { + throw wrapException("Error loading action "+name, e); + } } private final void processZipEntries(IZipEntryWithContextProcessor processor) { @@ -194,38 +201,48 @@ private static final class ActionLoadResult { private final SignedTextDescriptor signedTextDescriptor; private final ActionProperties properties; - @SneakyThrows final Action asAction() { - var payload = signedTextDescriptor.getPayload(); - var signatureStatus = signedTextDescriptor.getSignatureStatus(); - var result = yamlObjectMapper.readValue(payload, Action.class); - var properties = this.properties.toBuilder().signatureStatus(signatureStatus).build(); - result.postLoad(properties); - return result; + try { + var payload = signedTextDescriptor.getPayload(); + var signatureStatus = signedTextDescriptor.getSignatureStatus(); + var result = yamlObjectMapper.readValue(payload, Action.class); + var properties = this.properties.toBuilder().signatureStatus(signatureStatus).build(); + result.postLoad(properties); + return result; + } catch ( Exception e ) { + throw createException(properties, e); + } } public String asString() { return signedTextDescriptor.getPayload(); } - @SneakyThrows final ObjectNode asJson() { - var payload = signedTextDescriptor.getPayload(); - var signatureStatus = signedTextDescriptor.getSignatureStatus(); - String name = properties.getName(); - boolean custom = properties.isCustom(); - var customString = custom?"Yes":"No"; - // TODO see ActionLoader#loadSignedTextDescriptor; for internal actions - // we currently don't evaluate signatures until we implement functionality - // for signing these during or after build. - var signatureString = !custom || signatureStatus==SignatureStatus.VALID_SIGNATURE - ? "Valid" : "Invalid"; - return yamlObjectMapper.readValue(payload, ObjectNode.class) - .put("name", name) - .put("custom", custom) - .put("customString", customString) - .put("signatureStatus", signatureStatus.toString()) - .put("signatureString", signatureString); + try { + var payload = signedTextDescriptor.getPayload(); + var signatureStatus = signedTextDescriptor.getSignatureStatus(); + String name = properties.getName(); + boolean custom = properties.isCustom(); + var customString = custom?"Yes":"No"; + // TODO see ActionLoader#loadSignedTextDescriptor; for internal actions + // we currently don't evaluate signatures until we implement functionality + // for signing these during or after build. + var signatureString = !custom || signatureStatus==SignatureStatus.VALID_SIGNATURE + ? "Valid" : "Invalid"; + return yamlObjectMapper.readValue(payload, ObjectNode.class) + .put("name", name) + .put("custom", custom) + .put("customString", customString) + .put("signatureStatus", signatureStatus.toString()) + .put("signatureString", signatureString); + } catch ( Exception e ) { + throw createException(properties, e); + } + } + + private final RuntimeException createException(ActionProperties properties, Exception e) { + return wrapException("Error loading action "+properties.getName(), e); } } @@ -338,6 +355,11 @@ private static final String failedMessage(SignedTextDescriptor descriptor) { } } + private static final RuntimeException wrapException(String msg, Exception e) { + if ( e instanceof AbortedByUserException ) { return (AbortedByUserException)e; } + return new IllegalStateException(msg, e); + } + @FunctionalInterface private static interface ActionLoadResultProcessor { Break process(ActionLoadResult loadResult); diff --git a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/cli/mixin/CommonOptionMixins.java b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/cli/mixin/CommonOptionMixins.java index 2488882254..d1a90196b5 100644 --- a/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/cli/mixin/CommonOptionMixins.java +++ b/fcli-core/fcli-common/src/main/java/com/fortify/cli/common/cli/mixin/CommonOptionMixins.java @@ -54,7 +54,7 @@ public void checkConfirmed(Object... promptArgs) { if ( response.equalsIgnoreCase(expectedResponse) ) { return; } else { - throw new IllegalStateException("Aborting: operation aborted by user"); + throw new AbortedByUserException("Aborting: operation aborted by user"); } } } @@ -77,5 +77,10 @@ private String getPlainPrompt(CommandSpec spec, Object... promptArgs) { } return prompt; } + + public static final class AbortedByUserException extends IllegalStateException { + private static final long serialVersionUID = 1L; + public AbortedByUserException(String msg) { super(msg); } + } } } diff --git a/fcli-core/fcli-common/src/main/resources/com/fortify/cli/common/i18n/FortifyCLIMessages.properties b/fcli-core/fcli-common/src/main/resources/com/fortify/cli/common/i18n/FortifyCLIMessages.properties index c96f5a834f..a995e3ffc8 100644 --- a/fcli-core/fcli-common/src/main/resources/com/fortify/cli/common/i18n/FortifyCLIMessages.properties +++ b/fcli-core/fcli-common/src/main/resources/com/fortify/cli/common/i18n/FortifyCLIMessages.properties @@ -42,6 +42,7 @@ fcli.action.sign.out = Output signed action YAML file fcli.action.sign.with = PEM file containing private key used for signing fcli.action.sign.info = YAML file containing informational properties to be added to the signed file fcli.action.sign.pubout = Optional path to write public key +fcli.action.resolver.from = Optional local or remote zip-file from which to load the action # Generic, non command-specific output and query options arggroup.output.heading = Output options:%n diff --git a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/action/cli/cmd/FoDActionCommands.java b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/action/cli/cmd/FoDActionCommands.java index 9211354af3..2d79dfb921 100644 --- a/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/action/cli/cmd/FoDActionCommands.java +++ b/fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/action/cli/cmd/FoDActionCommands.java @@ -19,11 +19,12 @@ @Command( name = "action", subcommands = { + // TODO Re-enable import & reset commands once re-implemented FoDActionGetCommand.class, FoDActionHelpCommand.class, - FoDActionImportCommand.class, + //FoDActionImportCommand.class, FoDActionListCommand.class, - FoDActionResetCommand.class, + //FoDActionResetCommand.class, FoDActionRunCommand.class, } ) diff --git a/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/action/cli/cmd/SSCActionCommands.java b/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/action/cli/cmd/SSCActionCommands.java index aacfdb5c95..afdcca178d 100644 --- a/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/action/cli/cmd/SSCActionCommands.java +++ b/fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/action/cli/cmd/SSCActionCommands.java @@ -19,11 +19,12 @@ @Command( name = "action", subcommands = { + // TODO Re-enable import & reset commands once re-implemented SSCActionGetCommand.class, SSCActionHelpCommand.class, - SSCActionImportCommand.class, + //SSCActionImportCommand.class, SSCActionListCommand.class, - SSCActionResetCommand.class, + //SSCActionResetCommand.class, SSCActionRunCommand.class, SSCActionSignCommand.class, }