From 25e14a6d7d012d359b4e2087ec4d7669b6b3035b Mon Sep 17 00:00:00 2001 From: brunovg Date: Tue, 3 Jan 2023 15:45:01 +0000 Subject: [PATCH 01/11] Create draft PR for #75 From c2bb9d8210ef937720defda0cde1685f0b462bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Gon=C3=A7alves?= Date: Tue, 3 Jan 2023 15:48:51 +0000 Subject: [PATCH 02/11] endpoint that validates expressions --- dil/pom.xml | 19 ++++++ .../dil/validation/ExpressionsValidator.java | 62 ++++++++++++++++++ .../assimbly/dil/validation/Validator.java | 9 +++ .../dil/validation/beans/Expression.java | 63 +++++++++++++++++++ .../expressions/ConstantValidator.java | 25 ++++++++ .../expressions/GroovyValidator.java | 29 +++++++++ .../expressions/JsonPathValidator.java | 25 ++++++++ .../expressions/SimpleValidator.java | 27 ++++++++ .../expressions/XPathValidator.java | 30 +++++++++ .../org/assimbly/integration/Integration.java | 4 +- .../integration/impl/BaseIntegration.java | 6 +- .../integration/impl/CamelIntegration.java | 9 +-- .../integrationrest/ValidationResource.java | 33 ++++++++-- pom.xml | 1 + 14 files changed, 332 insertions(+), 10 deletions(-) create mode 100644 dil/src/main/java/org/assimbly/dil/validation/ExpressionsValidator.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/Validator.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/beans/Expression.java create mode 100755 dil/src/main/java/org/assimbly/dil/validation/expressions/ConstantValidator.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/expressions/GroovyValidator.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/expressions/JsonPathValidator.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/expressions/SimpleValidator.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/expressions/XPathValidator.java diff --git a/dil/pom.xml b/dil/pom.xml index 69ed9142..57258781 100644 --- a/dil/pom.xml +++ b/dil/pom.xml @@ -48,6 +48,25 @@ utils ${assimbly.version} + + + org.codehaus.groovy + groovy + ${groovy-script.version} + provided + + + org.codehaus.groovy + groovy-jsr223 + ${groovy-script.version} + provided + + + org.codehaus.groovy + groovy-dateutil + ${groovy-script.version} + provided + diff --git a/dil/src/main/java/org/assimbly/dil/validation/ExpressionsValidator.java b/dil/src/main/java/org/assimbly/dil/validation/ExpressionsValidator.java new file mode 100644 index 00000000..98d12c17 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/ExpressionsValidator.java @@ -0,0 +1,62 @@ +package org.assimbly.dil.validation; + +import org.assimbly.dil.validation.beans.Expression; +import org.assimbly.dil.validation.expressions.*; +import org.assimbly.util.error.ValidationErrorMessage; + +import java.util.ArrayList; +import java.util.List; + +public class ExpressionsValidator { + + private static final ValidationErrorMessage EMPTY_EXPRESSION_ERROR = new ValidationErrorMessage("Empty expressions aren't allowed!"); + + private JsonPathValidator jsonPathValidator = new JsonPathValidator(); + private SimpleValidator simpleValidator = new SimpleValidator(); + private XPathValidator xpathValidator = new XPathValidator(); + private ConstantValidator constantValidator = new ConstantValidator(); + private GroovyValidator groovyValidator = new GroovyValidator(); + + public List validate(List expressions) { + + List validationErrors = new ArrayList<>(); + + if (expressions.isEmpty()) { + validationErrors.add(EMPTY_EXPRESSION_ERROR); + return validationErrors; + } + + for (Expression expression : expressions) { + ValidationErrorMessage error; + + switch(expression.getExpressionType()) { + case "constant": + error = constantValidator.validate(expression); + break; + case "groovy": + error = groovyValidator.validate(expression); + break; + case "jsonpath": + error = jsonPathValidator.validate(expression); + break; + case "simple": + error = simpleValidator.validate(expression); + break; + case "xpath": + error = xpathValidator.validate(expression); + break; + default: + throw new RuntimeException("Dovetail could not validate the type of expression submitted."); + } + + if (error != null) { + validationErrors.add(error); + } + } + + if (validationErrors.isEmpty()) + return null; + + return validationErrors; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/Validator.java b/dil/src/main/java/org/assimbly/dil/validation/Validator.java new file mode 100644 index 00000000..3f613842 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/Validator.java @@ -0,0 +1,9 @@ +package org.assimbly.dil.validation; + +import org.assimbly.dil.validation.beans.Expression; +import org.assimbly.util.error.ValidationErrorMessage; + +public interface Validator { + + ValidationErrorMessage validate(Expression expression); +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/beans/Expression.java b/dil/src/main/java/org/assimbly/dil/validation/beans/Expression.java new file mode 100644 index 00000000..ca7f0d2a --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/beans/Expression.java @@ -0,0 +1,63 @@ +package org.assimbly.dil.validation.beans; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Expression { + + private String id; + + private String name; + private String expression; + private String expressionType; + private String nextNode; + + public Expression() { } + + public Expression(String name, String expression, String expressionType, String nextNode) { + this.name = name; + this.expression = expression; + this.expressionType = expressionType; + this.nextNode = nextNode; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getExpression() { + return expression; + } + + public void setExpression(String expression) { + this.expression = expression; + } + + public String getNextNode() { + return nextNode; + } + + public void setNextNode(String nextNode) { + this.nextNode = nextNode; + } + + @JsonProperty("_id") + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getExpressionType() { + return expressionType; + } + + public void setExpressionType(String expressionType) { + this.expressionType = expressionType; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/expressions/ConstantValidator.java b/dil/src/main/java/org/assimbly/dil/validation/expressions/ConstantValidator.java new file mode 100755 index 00000000..3e336087 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/expressions/ConstantValidator.java @@ -0,0 +1,25 @@ +package org.assimbly.dil.validation.expressions; + +import org.apache.camel.language.constant.ConstantLanguage; +import org.assimbly.dil.validation.beans.Expression; +import org.assimbly.dil.validation.Validator; +import org.assimbly.util.error.ValidationErrorMessage; + +public class ConstantValidator implements Validator { + + @Override + public ValidationErrorMessage validate(Expression expression){ + + try { + ConstantLanguage.constant(expression.getExpression()); + } catch (Exception e) { + if(expression.getName() == null) { + return new ValidationErrorMessage(e.getMessage()); + } + + return new ValidationErrorMessage("[" + expression.getName() + "]: " + e.getMessage()); + } + + return null; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/expressions/GroovyValidator.java b/dil/src/main/java/org/assimbly/dil/validation/expressions/GroovyValidator.java new file mode 100644 index 00000000..e9ece677 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/expressions/GroovyValidator.java @@ -0,0 +1,29 @@ +package org.assimbly.dil.validation.expressions; + +import org.assimbly.dil.validation.beans.Expression; +import org.assimbly.dil.validation.Validator; +import org.assimbly.util.error.ValidationErrorMessage; +import org.springframework.scripting.groovy.GroovyScriptEvaluator; +import org.springframework.scripting.support.StaticScriptSource; + +public class GroovyValidator implements Validator { + + @Override + public ValidationErrorMessage validate(Expression expression){ + + if(expression.getName() == null || expression.getName().isEmpty()) + return new ValidationErrorMessage("Header name cannot be empty"); + else if(expression.getExpression() == null || expression.getExpression().isEmpty()) + return new ValidationErrorMessage("Expression cannot be empty"); + else { + try { + GroovyScriptEvaluator groovyScriptEvaluator = new GroovyScriptEvaluator(); + groovyScriptEvaluator.evaluate(new StaticScriptSource(expression.getExpression())); + } catch (Exception e) { + return new ValidationErrorMessage("[" + expression.getName() + "]: " + e.getMessage()); + } + } + + return null; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/expressions/JsonPathValidator.java b/dil/src/main/java/org/assimbly/dil/validation/expressions/JsonPathValidator.java new file mode 100644 index 00000000..2e7e1ed0 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/expressions/JsonPathValidator.java @@ -0,0 +1,25 @@ +package org.assimbly.dil.validation.expressions; + +import com.jayway.jsonpath.InvalidPathException; +import com.jayway.jsonpath.JsonPath; +import org.assimbly.dil.validation.beans.Expression; +import org.assimbly.dil.validation.Validator; +import org.assimbly.util.error.ValidationErrorMessage; + +public class JsonPathValidator implements Validator { + + @Override + public ValidationErrorMessage validate(Expression expression){ + try { + JsonPath path = JsonPath.compile(expression.getExpression()); + } catch(InvalidPathException e) { + if(expression.getName() == null) { + return new ValidationErrorMessage(e.getMessage()); + } + + return new ValidationErrorMessage("[" + expression.getName() + "]: " + e.getMessage()); + } + + return null; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/expressions/SimpleValidator.java b/dil/src/main/java/org/assimbly/dil/validation/expressions/SimpleValidator.java new file mode 100644 index 00000000..bb3c9644 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/expressions/SimpleValidator.java @@ -0,0 +1,27 @@ +package org.assimbly.dil.validation.expressions; + +import org.apache.camel.language.simple.SimpleLanguage; +import org.apache.camel.language.simple.types.SimpleIllegalSyntaxException; +import org.assimbly.dil.validation.beans.Expression; +import org.assimbly.dil.validation.Validator; +import org.assimbly.util.error.ValidationErrorMessage; + +public class SimpleValidator implements Validator { + + + @Override + public ValidationErrorMessage validate(Expression expression){ + try { + SimpleLanguage.simple(expression.getExpression()); + } catch (SimpleIllegalSyntaxException e) { + if(expression.getName() == null) { + return new ValidationErrorMessage(e.getMessage()); + } + + return new ValidationErrorMessage("[" + expression.getName() + "]: " + e.getMessage()); + } + + return null; + } + +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/expressions/XPathValidator.java b/dil/src/main/java/org/assimbly/dil/validation/expressions/XPathValidator.java new file mode 100644 index 00000000..bdf13ebc --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/expressions/XPathValidator.java @@ -0,0 +1,30 @@ +package org.assimbly.dil.validation.expressions; + +import net.sf.saxon.s9api.Processor; +import net.sf.saxon.s9api.SaxonApiException; +import net.sf.saxon.s9api.XPathCompiler; +import org.assimbly.dil.validation.beans.Expression; +import org.assimbly.dil.validation.Validator; +import org.assimbly.util.error.ValidationErrorMessage; + +public class XPathValidator implements Validator { + + @Override + public ValidationErrorMessage validate(Expression expression){ + try { + Processor proc = new Processor(false); + XPathCompiler xpath = proc.newXPathCompiler(); + + xpath.compile(expression.getExpression()); + } catch (SaxonApiException e) { + if(expression.getName() == null) { + return new ValidationErrorMessage(e.getMessage()); + } + + return new ValidationErrorMessage("[" + expression.getName() + "]: " + e.getMessage()); + } + + return null; + } +} + diff --git a/integration/src/main/java/org/assimbly/integration/Integration.java b/integration/src/main/java/org/assimbly/integration/Integration.java index 5a91b67c..c8d5fd82 100644 --- a/integration/src/main/java/org/assimbly/integration/Integration.java +++ b/integration/src/main/java/org/assimbly/integration/Integration.java @@ -4,7 +4,9 @@ import org.apache.camel.ConsumerTemplate; import org.apache.camel.ProducerTemplate; import org.apache.camel.spi.EventNotifier; +import org.assimbly.dil.validation.beans.Expression; import org.assimbly.util.EncryptionUtil; +import org.assimbly.util.error.ValidationErrorMessage; import java.security.cert.Certificate; import java.util.List; @@ -853,7 +855,7 @@ public interface Integration { * @param expression the expression (for example simple, xpath, jsonpath or Groovy) * @return result of validation */ - public String validateExpression(String expression); + public List validateExpressions(List expressions); /** * Validates a ftp expression diff --git a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java index 451446eb..eaff334f 100644 --- a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java +++ b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java @@ -4,12 +4,14 @@ import org.apache.camel.ConsumerTemplate; import org.apache.camel.ProducerTemplate; import org.apache.camel.spi.EventNotifier; +import org.assimbly.dil.validation.beans.Expression; import org.assimbly.integration.Integration; import org.assimbly.dil.transpiler.JSONFileConfiguration; import org.assimbly.dil.transpiler.XMLFileConfiguration; import org.assimbly.dil.transpiler.YAMLFileConfiguration; import org.assimbly.util.BaseDirectory; import org.assimbly.util.IntegrationUtil; +import org.assimbly.util.error.ValidationErrorMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -401,13 +403,15 @@ public String testConnection(String host, int port, int timeOut) { public abstract String sendRequestWithHeaders(String uri, Object messageBody, TreeMap messageHeaders); + // validate + public abstract String validateCron(String cron); public abstract String validateCertificate(String certificate); public abstract String validateUrl(String url); - public abstract String validateExpression(String expression); + public abstract List validateExpressions(List expressions); public abstract String validateFtp(String ftp); diff --git a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java index 5651ae49..0d700263 100644 --- a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java +++ b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java @@ -31,6 +31,7 @@ import org.assimbly.dil.blocks.beans.UuidExtensionFunction; import org.assimbly.dil.blocks.processors.*; import org.assimbly.dil.loader.FlowLoaderReport; +import org.assimbly.dil.validation.ExpressionsValidator; import org.assimbly.docconverter.DocConverter; import org.assimbly.integration.loader.ConnectorRoute; import org.assimbly.dil.loader.FlowLoader; @@ -38,8 +39,8 @@ import org.assimbly.dil.transpiler.ssl.SSLConfiguration; import org.assimbly.dil.event.EventCollector; import org.assimbly.util.*; +import org.assimbly.util.error.ValidationErrorMessage; import org.assimbly.util.file.DirectoryWatcher; -import org.assimbly.util.mail.ExtendedHeaderFilterStrategy; import org.jasypt.properties.EncryptableProperties; import org.json.JSONArray; import org.json.JSONObject; @@ -192,7 +193,6 @@ public void setDefaultBlocks() throws Exception { registry.bind("customHttpBinding", new CustomHttpBinding()); registry.bind("uuid-function", new UuidExtensionFunction()); - registry.bind("ExtendedHeaderFilterStrategy", new ExtendedHeaderFilterStrategy()); context.addComponent("sync", new DirectVmComponent()); context.addComponent("async", new VmComponent()); @@ -1968,8 +1968,9 @@ public String validateUrl(String url) { } @Override - public String validateExpression(String expression) { - return null; + public List validateExpressions(List expressions) { + ExpressionsValidator expressionValidator = new ExpressionsValidator(); + return expressionValidator.validate(expressions); } @Override diff --git a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java index c0c0fb3b..4dc01e94 100644 --- a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java +++ b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java @@ -1,7 +1,11 @@ package org.assimbly.integrationrest; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.Parameter; +import org.assimbly.dil.validation.beans.Expression; import org.assimbly.integration.Integration; +import org.assimbly.util.error.ValidationErrorMessage; import org.assimbly.util.rest.ResponseUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -9,6 +13,9 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.io.ByteArrayOutputStream; +import java.util.List; + /** * Resource to return information about the currently running Spring profiles. */ @@ -24,7 +31,7 @@ public class ValidationResource { private Integration integration; - //validatons + //validations @GetMapping(path = "/validation/{integrationId}/cron", produces = {"application/xml","application/json","text/plain"}) public ResponseEntity validateCron(@Parameter(hidden = true) @RequestHeader("Accept") String mediaType, @PathVariable Long integrationId) throws Exception { @@ -70,13 +77,31 @@ public ResponseEntity validateUrl(@Parameter(hidden = true) @RequestHead @PostMapping(path = "/validation/{integrationId}/expression", consumes = {"application/json"}, produces = {"application/xml","application/json","text/plain"}) - public ResponseEntity validateExpression(@Parameter(hidden = true) @RequestHeader("Accept") String mediaType, @RequestHeader(value = "StopTest", defaultValue = "false") boolean stopTest, @PathVariable Long integrationId, @RequestBody String body) throws Exception { + public ResponseEntity validateExpression( + @Parameter(hidden = true) @RequestHeader("Accept") String mediaType, + @RequestHeader(value = "StopTest", defaultValue = "false") boolean stopTest, + @PathVariable Long integrationId, @RequestBody String body + ) throws Exception { try { - integration = integrationResource.getIntegration(); - return ResponseUtil.createSuccessResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/expression", "", "", ""); + List expressionsList = null; + if(body!=null){ + expressionsList = new ObjectMapper().readValue(body, new TypeReference>(){}); + } + + List expressionResp = integration.validateExpressions(expressionsList); + + if(expressionResp!=null) { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(out, expressionResp); + return ResponseUtil.createSuccessResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/expression", out.toString(), "", ""); + } else { + return ResponseUtil.createNoContentResponse(integrationId, mediaType); + } + } catch (Exception e) { log.error("Error",e); return ResponseUtil.createFailureResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/expression", e.getMessage(), "", ""); diff --git a/pom.xml b/pom.xml index 715b9955..20e40070 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,7 @@ 3.8.1 4.2.13 + 2.5.4 1.7.1 1.6.13 From 875f2670c37d74583aa64ef1dd1a4cef55ae548b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Gon=C3=A7alves?= Date: Wed, 4 Jan 2023 12:01:22 +0000 Subject: [PATCH 03/11] ftp endpoint --- dil/pom.xml | 11 ++ .../assimbly/dil/validation/FtpValidator.java | 162 ++++++++++++++++++ .../dil/validation/beans/FtpSettings.java | 70 ++++++++ .../org/assimbly/integration/Integration.java | 3 +- .../integration/impl/BaseIntegration.java | 3 +- .../integration/impl/CamelIntegration.java | 7 +- .../integrationrest/ValidationResource.java | 26 ++- pom.xml | 3 + 8 files changed, 278 insertions(+), 7 deletions(-) create mode 100644 dil/src/main/java/org/assimbly/dil/validation/FtpValidator.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/beans/FtpSettings.java diff --git a/dil/pom.xml b/dil/pom.xml index 57258781..76fffbf6 100644 --- a/dil/pom.xml +++ b/dil/pom.xml @@ -67,6 +67,17 @@ ${groovy-script.version} provided + + + org.apache.servicemix.bundles + org.apache.servicemix.bundles.jsch + ${jsch.version} + + + commons-net + commons-net + ${commons-net.version} + diff --git a/dil/src/main/java/org/assimbly/dil/validation/FtpValidator.java b/dil/src/main/java/org/assimbly/dil/validation/FtpValidator.java new file mode 100644 index 00000000..0459cc73 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/FtpValidator.java @@ -0,0 +1,162 @@ +package org.assimbly.dil.validation; + +import com.jcraft.jsch.Channel; +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; +import org.apache.commons.net.ftp.FTPClient; +import org.apache.commons.net.ftp.FTPReply; +import org.apache.commons.net.ftp.FTPSClient; +import org.assimbly.dil.validation.beans.FtpSettings; +import org.assimbly.util.error.ValidationErrorMessage; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.ConnectException; +import java.net.UnknownHostException; + +public class FtpValidator { + + private static final int TIMEOUT = 3000; + private static final ValidationErrorMessage UNREACHABLE_ERROR = + new ValidationErrorMessage("Cannot login into FTP from the Dovetail server!"); + + public ValidationErrorMessage validate(FtpSettings ftpSettings) { + + if (ftpSettings.getProtocol().equalsIgnoreCase("ftp")) + return checkFtpConnection(ftpSettings.getUser(), ftpSettings.getPwd(), ftpSettings.getHost(), ftpSettings.getPort(), false); + else if (ftpSettings.getProtocol().equalsIgnoreCase("ftps")) + return checkFtpConnection(ftpSettings.getUser(), ftpSettings.getPwd(), ftpSettings.getHost(), ftpSettings.getPort(), true); + else + return checkSFtpConnection(ftpSettings.getUser(), ftpSettings.getPwd(), ftpSettings.getHost(), ftpSettings.getPort(), ftpSettings.getPkf(), ftpSettings.getPkfd()); + } + + private Session setupDefaultSession(JSch jsch, String userName, String host, int port) throws JSchException { + Session session = jsch.getSession(userName, host, port); + session.setConfig("StrictHostKeyChecking", "no"); + + return session; + } + + private ValidationErrorMessage checkSFtpConnection(String userName, String password, String host, int port, String privateKeyFilePath, String privateKeyFileData) { + Session session = null; + Channel channel = null; + File tempFile = null; + JSch jsch; + + try { + jsch = new JSch(); + + session = setupDefaultSession(jsch, userName, host, port); + + if (password != null && !password.isEmpty()) + session.setPassword(password); + + if (privateKeyFileData != null && !privateKeyFileData.isEmpty()) { + tempFile = File.createTempFile("temp", ""); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile))){ + writer.write(privateKeyFileData); + } + jsch.addIdentity(tempFile.getAbsolutePath()); + } + else if (privateKeyFilePath != null && !privateKeyFilePath.isEmpty()) + jsch.addIdentity(privateKeyFilePath); + + session.connect(TIMEOUT); + + channel = session.openChannel("sftp"); + channel.connect(); + + if (!channel.isConnected()) + return UNREACHABLE_ERROR; + + } catch (Exception e) { + return handleSftpException(e); + } finally { + if (channel != null) + channel.disconnect(); + if (session != null) + session.disconnect(); + if (tempFile != null) + tempFile.delete(); + } + + return null; + } + + private ValidationErrorMessage handleSftpException (Exception exception) { + Throwable cause = exception.getCause(); + + if (cause != null) { + return getMessageFromCause(cause); + } else { + return getMessageFromException(exception); + } + } + + private ValidationErrorMessage getMessageFromCause (Throwable cause) { + if (cause instanceof ConnectException) { + return new ValidationErrorMessage("Connection refused"); + } else if (cause instanceof UnknownHostException) { + return new ValidationErrorMessage("Host name could not be resolved"); + } else { + return new ValidationErrorMessage(cause.getMessage()); + } + } + + private ValidationErrorMessage getMessageFromException (Exception exception) { + if (exception.getMessage().contains("ConnectException")) { + return new ValidationErrorMessage("Connection refused"); + } else if (exception.getMessage().contains("UnknownHostException")) { + return new ValidationErrorMessage("Host name could not be resolved"); + } else { + return new ValidationErrorMessage(exception.getMessage()); + } + } + + private ValidationErrorMessage checkFtpConnection(String userName, String password, String host, int port, boolean secure) { + FTPClient ftp = null; + + try { + if(secure) { + ftp = new FTPSClient(); + } else { + ftp = new FTPClient(); + } + + ftp.connect(host, port); + + // After connection attempt, you should check the reply code to verify success. + int reply = ftp.getReplyCode(); + if (!FTPReply.isPositiveCompletion(reply)) { + ftp.disconnect(); + + return UNREACHABLE_ERROR; + } + + if (!ftp.login(userName, password)) { + ftp.logout(); + + return UNREACHABLE_ERROR; + } + } catch (ConnectException e){ + return new ValidationErrorMessage("Connection refused"); + } catch (UnknownHostException e) { + return new ValidationErrorMessage("Host name could not be resolved"); + } catch (Exception e) { + return new ValidationErrorMessage(e.getMessage()); + } finally { + if (ftp != null && ftp.isConnected()) { + try { + ftp.disconnect(); + } catch (IOException ioe) { + // Do nothing + } + } + } + + return null; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/beans/FtpSettings.java b/dil/src/main/java/org/assimbly/dil/validation/beans/FtpSettings.java new file mode 100644 index 00000000..d6092c16 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/beans/FtpSettings.java @@ -0,0 +1,70 @@ +package org.assimbly.dil.validation.beans; + +public class FtpSettings { + + private String user; + private String host; + private String pwd; + private int port; + private String protocol; + private String pkf; + private String pkfd; + + public FtpSettings() { } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getPwd() { + return pwd; + } + + public void setPwd(String pwd) { + this.pwd = pwd; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getPkf() { + return pkf; + } + + public void setPkf(String pkf) { + this.pkf = pkf; + } + + public String getPkfd() { + return pkfd; + } + + public void setPkfd(String pkfd) { + this.pkfd = pkfd; + } +} diff --git a/integration/src/main/java/org/assimbly/integration/Integration.java b/integration/src/main/java/org/assimbly/integration/Integration.java index c8d5fd82..8d101a57 100644 --- a/integration/src/main/java/org/assimbly/integration/Integration.java +++ b/integration/src/main/java/org/assimbly/integration/Integration.java @@ -5,6 +5,7 @@ import org.apache.camel.ProducerTemplate; import org.apache.camel.spi.EventNotifier; import org.assimbly.dil.validation.beans.Expression; +import org.assimbly.dil.validation.beans.FtpSettings; import org.assimbly.util.EncryptionUtil; import org.assimbly.util.error.ValidationErrorMessage; @@ -863,7 +864,7 @@ public interface Integration { * @param ftp * @return result of validation */ - public String validateFtp(String ftp); + public ValidationErrorMessage validateFtp(FtpSettings ftpSettings); /** * Validates a regex expression diff --git a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java index eaff334f..613b98ba 100644 --- a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java +++ b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java @@ -5,6 +5,7 @@ import org.apache.camel.ProducerTemplate; import org.apache.camel.spi.EventNotifier; import org.assimbly.dil.validation.beans.Expression; +import org.assimbly.dil.validation.beans.FtpSettings; import org.assimbly.integration.Integration; import org.assimbly.dil.transpiler.JSONFileConfiguration; import org.assimbly.dil.transpiler.XMLFileConfiguration; @@ -413,7 +414,7 @@ public String testConnection(String host, int port, int timeOut) { public abstract List validateExpressions(List expressions); - public abstract String validateFtp(String ftp); + public abstract ValidationErrorMessage validateFtp(FtpSettings ftpSettings); public abstract String validateRegex(String regex); diff --git a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java index 0d700263..f43dbdf8 100644 --- a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java +++ b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java @@ -32,6 +32,8 @@ import org.assimbly.dil.blocks.processors.*; import org.assimbly.dil.loader.FlowLoaderReport; import org.assimbly.dil.validation.ExpressionsValidator; +import org.assimbly.dil.validation.FtpValidator; +import org.assimbly.dil.validation.beans.FtpSettings; import org.assimbly.docconverter.DocConverter; import org.assimbly.integration.loader.ConnectorRoute; import org.assimbly.dil.loader.FlowLoader; @@ -1974,8 +1976,9 @@ public List validateExpressions(List validateExpression( } @PostMapping(path = "/validation/{integrationId}/ftp", consumes = {"application/json"}, produces = {"application/xml","application/json","text/plain"}) - public ResponseEntity validateFtp(@Parameter(hidden = true) @RequestHeader("Accept") String mediaType, @RequestHeader(value = "StopTest", defaultValue = "false") boolean stopTest, @PathVariable Long integrationId, @RequestBody String body) throws Exception { + public ResponseEntity validateFtp( + @Parameter(hidden = true) @RequestHeader("Accept") String mediaType, + @RequestHeader(value = "StopTest",defaultValue = "false") boolean stopTest, + @PathVariable Long integrationId, @RequestBody String body + ) throws Exception { try { - integration = integrationResource.getIntegration(); - return ResponseUtil.createSuccessResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/ftp", "", "", ""); + FtpSettings ftpSettings = null; + if(body!=null){ + ftpSettings = new ObjectMapper().readValue(body, FtpSettings.class); + } + + ValidationErrorMessage ftpResp = integration.validateFtp(ftpSettings); + + if(ftpResp!=null) { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(out, ftpResp); + return ResponseUtil.createSuccessResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/ftp", out.toString(), "", ""); + } else { + return ResponseUtil.createNoContentResponse(integrationId, mediaType); + } + } catch (Exception e) { log.error("Error",e); return ResponseUtil.createFailureResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/ftp", e.getMessage(), "", ""); diff --git a/pom.xml b/pom.xml index 20e40070..2bf569a0 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,9 @@ 2.5.4 1.7.1 1.6.13 + + 3.6 + 0.1.48_1 From 8d4eda953ef058538f80aec9b952de2b8c7e1cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Gon=C3=A7alves?= Date: Wed, 4 Jan 2023 15:54:52 +0000 Subject: [PATCH 04/11] regex endpoint --- .../dil/validation/RegexValidator.java | 34 +++++++++++++++++++ .../assimbly/dil/validation/beans/Regex.java | 20 +++++++++++ .../org/assimbly/integration/Integration.java | 8 ++--- .../integration/impl/BaseIntegration.java | 3 +- .../integration/impl/CamelIntegration.java | 7 ++-- .../integrationrest/ValidationResource.java | 33 ++++++++++++++++-- 6 files changed, 94 insertions(+), 11 deletions(-) create mode 100644 dil/src/main/java/org/assimbly/dil/validation/RegexValidator.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/beans/Regex.java diff --git a/dil/src/main/java/org/assimbly/dil/validation/RegexValidator.java b/dil/src/main/java/org/assimbly/dil/validation/RegexValidator.java new file mode 100644 index 00000000..046c8e2c --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/RegexValidator.java @@ -0,0 +1,34 @@ +package org.assimbly.dil.validation; + +import org.assimbly.dil.validation.beans.Regex; +import org.assimbly.util.error.ValidationErrorMessage; + +import java.util.AbstractMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +public class RegexValidator { + + public AbstractMap.SimpleEntry validate(Regex expression) { + + AbstractMap.SimpleEntry response = null; + String regex = expression.getExpression(); + + if (regex.isEmpty()) { + return new AbstractMap.SimpleEntry(-1, "Regex cannot be empty"); + } + + try { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(""); + response = new AbstractMap.SimpleEntry(1, String.valueOf(matcher.groupCount())); + + } catch (PatternSyntaxException e) { + response = new AbstractMap.SimpleEntry(-1, e.getMessage()); + } + + return response; + } + +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/beans/Regex.java b/dil/src/main/java/org/assimbly/dil/validation/beans/Regex.java new file mode 100644 index 00000000..e2c88969 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/beans/Regex.java @@ -0,0 +1,20 @@ +package org.assimbly.dil.validation.beans; + +public class Regex { + + private String expression; + + public Regex() {} + + public Regex(String expression) { + this.expression = expression; + } + + public String getExpression() { + return expression; + } + + public void setExpression(String expression) { + this.expression = expression; + } +} diff --git a/integration/src/main/java/org/assimbly/integration/Integration.java b/integration/src/main/java/org/assimbly/integration/Integration.java index 8d101a57..89ceccf4 100644 --- a/integration/src/main/java/org/assimbly/integration/Integration.java +++ b/integration/src/main/java/org/assimbly/integration/Integration.java @@ -6,14 +6,12 @@ import org.apache.camel.spi.EventNotifier; import org.assimbly.dil.validation.beans.Expression; import org.assimbly.dil.validation.beans.FtpSettings; +import org.assimbly.dil.validation.beans.Regex; import org.assimbly.util.EncryptionUtil; import org.assimbly.util.error.ValidationErrorMessage; import java.security.cert.Certificate; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.TreeMap; +import java.util.*; /** *
@@ -872,7 +870,7 @@ public interface Integration {
 	 * @param  regex the regex expression
 	 * @return result of validation
 	 */
-	public String validateRegex(String regex);
+	public AbstractMap.SimpleEntry validateRegex(Regex regex);
 
 	/**
 	 * Validates a script
diff --git a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java
index 613b98ba..c4c58a65 100644
--- a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java
+++ b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java
@@ -6,6 +6,7 @@
 import org.apache.camel.spi.EventNotifier;
 import org.assimbly.dil.validation.beans.Expression;
 import org.assimbly.dil.validation.beans.FtpSettings;
+import org.assimbly.dil.validation.beans.Regex;
 import org.assimbly.integration.Integration;
 import org.assimbly.dil.transpiler.JSONFileConfiguration;
 import org.assimbly.dil.transpiler.XMLFileConfiguration;
@@ -416,7 +417,7 @@ public String testConnection(String host, int port, int timeOut) {
 
 	public abstract ValidationErrorMessage validateFtp(FtpSettings ftpSettings);
 
-	public abstract String validateRegex(String regex);
+	public abstract AbstractMap.SimpleEntry validateRegex(Regex regex);
 
 	public abstract String validateScript(String script);
 
diff --git a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java
index f43dbdf8..42f09b07 100644
--- a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java
+++ b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java
@@ -33,7 +33,9 @@
 import org.assimbly.dil.loader.FlowLoaderReport;
 import org.assimbly.dil.validation.ExpressionsValidator;
 import org.assimbly.dil.validation.FtpValidator;
+import org.assimbly.dil.validation.RegexValidator;
 import org.assimbly.dil.validation.beans.FtpSettings;
+import org.assimbly.dil.validation.beans.Regex;
 import org.assimbly.docconverter.DocConverter;
 import org.assimbly.integration.loader.ConnectorRoute;
 import org.assimbly.dil.loader.FlowLoader;
@@ -1982,8 +1984,9 @@ public ValidationErrorMessage validateFtp(FtpSettings ftpSettings) {
 	}
 
 	@Override
-	public String validateRegex(String regex) {
-		return null;
+	public AbstractMap.SimpleEntry validateRegex(Regex regex) {
+		RegexValidator regexValidator = new RegexValidator();
+		return regexValidator.validate(regex);
 	}
 
 	@Override
diff --git a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java
index 9176b739..39a24438 100644
--- a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java
+++ b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java
@@ -5,6 +5,7 @@
 import io.swagger.v3.oas.annotations.Parameter;
 import org.assimbly.dil.validation.beans.Expression;
 import org.assimbly.dil.validation.beans.FtpSettings;
+import org.assimbly.dil.validation.beans.Regex;
 import org.assimbly.integration.Integration;
 import org.assimbly.util.error.ValidationErrorMessage;
 import org.assimbly.util.rest.ResponseUtil;
@@ -15,6 +16,7 @@
 import org.springframework.web.bind.annotation.*;
 
 import java.io.ByteArrayOutputStream;
+import java.util.AbstractMap;
 import java.util.HashMap;
 import java.util.List;
 
@@ -145,13 +147,38 @@ public ResponseEntity validateFtp(
     }
 
     @PostMapping(path = "/validation/{integrationId}/regex", consumes =  {"application/json"}, produces = {"application/xml","application/json","text/plain"})
-    public ResponseEntity validateRegex(@Parameter(hidden = true) @RequestHeader("Accept") String mediaType, @RequestHeader(value = "StopTest", defaultValue = "false") boolean stopTest, @PathVariable Long integrationId, @RequestBody String body) throws Exception {
+    public ResponseEntity validateRegex(
+            @Parameter(hidden = true) @RequestHeader("Accept") String mediaType,
+            @RequestHeader(value = "StopTest", defaultValue = "false") boolean stopTest,
+            @PathVariable Long integrationId, @RequestBody String body
+    ) throws Exception {
 
         try {
-
             integration = integrationResource.getIntegration();
 
-            return ResponseUtil.createSuccessResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/regex", "", "", "");
+            Regex regex = null;
+            if(body!=null){
+                regex = new ObjectMapper().readValue(body, Regex.class);
+            }
+
+            AbstractMap.SimpleEntry regexResp = integration.validateRegex(regex);
+
+            if(regexResp!=null) {
+                if (regexResp.getKey().equals("-1")) {
+                    ValidationErrorMessage validationErrorMessage = new ValidationErrorMessage();
+                    validationErrorMessage.setError((String)regexResp.getValue());
+                    final ByteArrayOutputStream out = new ByteArrayOutputStream();
+                    final ObjectMapper mapper = new ObjectMapper();
+                    mapper.writeValue(out, regexResp);
+                    return ResponseUtil.createFailureResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/regex", out.toString(), "", "");
+                } else {
+                    // success - return group count
+                    return ResponseUtil.createSuccessResponse(integrationId, mediaType, "/validation/{integrationId}/regex", (String)regexResp.getValue());
+                }
+            } else {
+                return ResponseUtil.createFailureResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/regex", "", "", "");
+            }
+
         } catch (Exception e) {
             log.error("Error",e);
             return ResponseUtil.createFailureResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/regex", e.getMessage(), "", "");

From 00933fb3233df11e706b45b11e72d6c6ca18164b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bruno=20Gon=C3=A7alves?= 
Date: Wed, 4 Jan 2023 17:05:07 +0000
Subject: [PATCH 05/11] cron endpoint

---
 .../dil/validation/CronValidator.java         | 23 +++++++++++++++++++
 .../org/assimbly/integration/Integration.java |  2 +-
 .../integration/impl/BaseIntegration.java     |  2 +-
 .../integration/impl/CamelIntegration.java    |  6 +++--
 .../integrationrest/ValidationResource.java   | 19 ++++++++++++---
 5 files changed, 45 insertions(+), 7 deletions(-)
 create mode 100755 dil/src/main/java/org/assimbly/dil/validation/CronValidator.java

diff --git a/dil/src/main/java/org/assimbly/dil/validation/CronValidator.java b/dil/src/main/java/org/assimbly/dil/validation/CronValidator.java
new file mode 100755
index 00000000..9229f869
--- /dev/null
+++ b/dil/src/main/java/org/assimbly/dil/validation/CronValidator.java
@@ -0,0 +1,23 @@
+package org.assimbly.dil.validation;
+
+import org.assimbly.util.error.ValidationErrorMessage;
+import org.quartz.CronExpression;
+
+public class CronValidator {
+
+    private static final ValidationErrorMessage EMPTY_CRON_ERROR = new ValidationErrorMessage("Empty crons aren't allowed!");
+
+    public ValidationErrorMessage validate(String cronExpression) {
+
+        if (cronExpression.isEmpty())
+            return EMPTY_CRON_ERROR;
+
+        try {
+            new CronExpression(cronExpression);
+        } catch (Exception e) {
+            return new ValidationErrorMessage("Cron Validation error: " + e.getMessage());
+        }
+
+        return null;
+    }
+}
diff --git a/integration/src/main/java/org/assimbly/integration/Integration.java b/integration/src/main/java/org/assimbly/integration/Integration.java
index 89ceccf4..1b5e0c9c 100644
--- a/integration/src/main/java/org/assimbly/integration/Integration.java
+++ b/integration/src/main/java/org/assimbly/integration/Integration.java
@@ -831,7 +831,7 @@ public interface Integration {
 	 * @param  cron the cron expression
 	 * @return result of validation
 	 */
-	public String validateCron(String cron);
+	public ValidationErrorMessage validateCron(String cronExpression);
 
 	/**
 	 * Validates a certificate
diff --git a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java
index c4c58a65..7427c4d6 100644
--- a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java
+++ b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java
@@ -407,7 +407,7 @@ public String testConnection(String host, int port, int timeOut) {
 
 	// validate
 
-	public abstract String validateCron(String cron);
+	public abstract ValidationErrorMessage validateCron(String cronExpression);
 
 	public abstract String validateCertificate(String certificate);
 
diff --git a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java
index 42f09b07..7e09a3b1 100644
--- a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java
+++ b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java
@@ -31,6 +31,7 @@
 import org.assimbly.dil.blocks.beans.UuidExtensionFunction;
 import org.assimbly.dil.blocks.processors.*;
 import org.assimbly.dil.loader.FlowLoaderReport;
+import org.assimbly.dil.validation.CronValidator;
 import org.assimbly.dil.validation.ExpressionsValidator;
 import org.assimbly.dil.validation.FtpValidator;
 import org.assimbly.dil.validation.RegexValidator;
@@ -1957,8 +1958,9 @@ public void deleteCertificateInKeystore(String keystoreName, String keystorePass
 	}
 
 	@Override
-	public String validateCron(String cron) {
-		return null;
+	public ValidationErrorMessage validateCron(String cronExpression) {
+		CronValidator cronValidator = new CronValidator();
+		return cronValidator.validate(cronExpression);
 	}
 
 	@Override
diff --git a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java
index 39a24438..9ef7f4e5 100644
--- a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java
+++ b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java
@@ -38,13 +38,26 @@ public class ValidationResource {
     //validations
 
     @GetMapping(path = "/validation/{integrationId}/cron", produces = {"application/xml","application/json","text/plain"})
-    public ResponseEntity validateCron(@Parameter(hidden = true) @RequestHeader("Accept") String mediaType, @PathVariable Long integrationId) throws Exception {
+    public ResponseEntity validateCron(
+            @Parameter(hidden = true) @RequestHeader("Accept") String mediaType,
+            @Parameter String expression,
+            @PathVariable Long integrationId
+    ) throws Exception {
 
         try {
-
             integration = integrationResource.getIntegration();
 
-            return ResponseUtil.createSuccessResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/cron", "", "", "");
+            ValidationErrorMessage cronResp = integration.validateCron(expression);
+
+            if(cronResp!=null) {
+                final ByteArrayOutputStream out = new ByteArrayOutputStream();
+                final ObjectMapper mapper = new ObjectMapper();
+                mapper.writeValue(out, cronResp);
+                return ResponseUtil.createSuccessResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/expression", out.toString(), "", "");
+            } else {
+                return ResponseUtil.createNoContentResponse(integrationId, mediaType);
+            }
+
         } catch (Exception e) {
             log.error("ErrorMessage",e);
             return ResponseUtil.createFailureResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/cron", e.getMessage(), "","");

From fcab053e84ba65c274804cfa4829b0f1ea1253e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bruno=20Gon=C3=A7alves?= 
Date: Thu, 5 Jan 2023 11:35:25 +0000
Subject: [PATCH 06/11] url endpoint

---
 .../assimbly/dil/validation/UrlValidator.java | 50 +++++++++++++++++++
 .../org/assimbly/integration/Integration.java |  2 +-
 .../integration/impl/BaseIntegration.java     |  2 +-
 .../integration/impl/CamelIntegration.java    | 10 ++--
 .../integrationrest/ValidationResource.java   | 18 +++++--
 5 files changed, 71 insertions(+), 11 deletions(-)
 create mode 100755 dil/src/main/java/org/assimbly/dil/validation/UrlValidator.java

diff --git a/dil/src/main/java/org/assimbly/dil/validation/UrlValidator.java b/dil/src/main/java/org/assimbly/dil/validation/UrlValidator.java
new file mode 100755
index 00000000..00fc20a3
--- /dev/null
+++ b/dil/src/main/java/org/assimbly/dil/validation/UrlValidator.java
@@ -0,0 +1,50 @@
+package org.assimbly.dil.validation;
+
+import org.assimbly.util.error.ValidationErrorMessage;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.UnknownHostException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class UrlValidator {
+
+    private static final int TIMEOUT = 5000;
+    private static final ValidationErrorMessage UNREACHABLE_ERROR = new ValidationErrorMessage("Url is not reachable from the server!");
+    private static final ValidationErrorMessage INVALID_URL_ERROR = new ValidationErrorMessage("Url is not valid!");
+
+    public ValidationErrorMessage validate(String url) {
+        final HttpURLConnection httpUrlConn;
+
+        try {
+            String decodedUrl = URLDecoder.decode(url, "UTF-8");
+
+            if(!validateURL(decodedUrl))
+                return INVALID_URL_ERROR;
+
+            httpUrlConn = (HttpURLConnection) new URL(decodedUrl).openConnection();
+
+            httpUrlConn.setRequestMethod("HEAD");
+
+            // Set timeouts in milliseconds
+            httpUrlConn.setConnectTimeout(TIMEOUT);
+            httpUrlConn.connect();
+            //need to trigger exception when no connection can be established
+            httpUrlConn.getResponseMessage();
+        } catch (UnknownHostException e) {
+            return UNREACHABLE_ERROR;
+        } catch (Exception e) {
+            return new ValidationErrorMessage(e.getMessage());
+        }
+
+        return null;
+    }
+
+    public static final boolean validateURL(String url) {
+        Pattern regex = Pattern.compile("^(https?):\\/\\/[-a-zA-Z0-9+&@#\\/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#\\/%=~_|]");
+        Matcher matcher = regex.matcher(url);
+        return matcher.find();
+    }
+}
diff --git a/integration/src/main/java/org/assimbly/integration/Integration.java b/integration/src/main/java/org/assimbly/integration/Integration.java
index 1b5e0c9c..b67d6d90 100644
--- a/integration/src/main/java/org/assimbly/integration/Integration.java
+++ b/integration/src/main/java/org/assimbly/integration/Integration.java
@@ -846,7 +846,7 @@ public interface Integration {
 	 * @param  url
 	 * @return result of validation
 	 */
-	public String validateUrl(String url);
+	public ValidationErrorMessage validateUrl(String url);
 
 	/**
 	 * Validates an expression
diff --git a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java
index 7427c4d6..2508d1a1 100644
--- a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java
+++ b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java
@@ -411,7 +411,7 @@ public String testConnection(String host, int port, int timeOut) {
 
 	public abstract String validateCertificate(String certificate);
 
-	public abstract String validateUrl(String url);
+	public abstract ValidationErrorMessage validateUrl(String url);
 
 	public abstract List validateExpressions(List expressions);
 
diff --git a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java
index 7e09a3b1..2fe8f517 100644
--- a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java
+++ b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java
@@ -31,10 +31,7 @@
 import org.assimbly.dil.blocks.beans.UuidExtensionFunction;
 import org.assimbly.dil.blocks.processors.*;
 import org.assimbly.dil.loader.FlowLoaderReport;
-import org.assimbly.dil.validation.CronValidator;
-import org.assimbly.dil.validation.ExpressionsValidator;
-import org.assimbly.dil.validation.FtpValidator;
-import org.assimbly.dil.validation.RegexValidator;
+import org.assimbly.dil.validation.*;
 import org.assimbly.dil.validation.beans.FtpSettings;
 import org.assimbly.dil.validation.beans.Regex;
 import org.assimbly.docconverter.DocConverter;
@@ -1969,8 +1966,9 @@ public String validateCertificate(String certificate) {
 	}
 
 	@Override
-	public String validateUrl(String url) {
-		return null;
+	public ValidationErrorMessage validateUrl(String url) {
+		UrlValidator urlValidator = new UrlValidator();
+		return urlValidator.validate(url);
 	}
 
 	@Override
diff --git a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java
index 9ef7f4e5..206f6f45 100644
--- a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java
+++ b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java
@@ -79,13 +79,25 @@ public ResponseEntity validateCertificate(@Parameter(hidden = true) @Req
     }
 
     @GetMapping(path = "/validation/{integrationId}/url", produces = {"application/xml","application/json","text/plain"})
-    public ResponseEntity validateUrl(@Parameter(hidden = true) @RequestHeader("Accept") String mediaType, @PathVariable Long integrationId) throws Exception {
+    public ResponseEntity validateUrl(
+            @Parameter(hidden = true) @RequestHeader("Accept") String mediaType,
+            @Parameter String httpUrl,
+            @PathVariable Long integrationId
+    ) throws Exception {
 
         try {
-
             integration = integrationResource.getIntegration();
 
-            return ResponseUtil.createSuccessResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/url", "", "", "");
+            ValidationErrorMessage urlResp = integration.validateUrl(httpUrl);
+
+            if(urlResp!=null) {
+                final ByteArrayOutputStream out = new ByteArrayOutputStream();
+                final ObjectMapper mapper = new ObjectMapper();
+                mapper.writeValue(out, urlResp);
+                return ResponseUtil.createSuccessResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/url", out.toString(), "", "");
+            } else {
+                return ResponseUtil.createNoContentResponse(integrationId, mediaType);
+            }
         } catch (Exception e) {
             log.error("ErrorMessage",e);
             return ResponseUtil.createFailureResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/url", e.getMessage(), "","");

From ad580be682ef69e657fa69932d5a4261b3ef131a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bruno=20Gon=C3=A7alves?= 
Date: Mon, 9 Jan 2023 15:24:59 +0000
Subject: [PATCH 07/11] httpsCertificate endpoint

---
 .../dil/transpiler/ssl/SSLConfiguration.java  |  29 +++++
 .../dil/validation/CertificateRetriever.java  |   9 ++
 .../validation/HttpsCertificateValidator.java | 119 ++++++++++++++++++
 .../https/CompositeTrustManager.java          |  82 ++++++++++++
 .../validation/https/FileBasedTrustStore.java | 106 ++++++++++++++++
 .../https/TrustedClientConfigurer.java        |  60 +++++++++
 .../org/assimbly/integration/Integration.java |   3 +-
 .../integration/impl/BaseIntegration.java     |   3 +-
 .../integration/impl/CamelIntegration.java    |  15 ++-
 .../integrationrest/ValidationResource.java   |  30 ++++-
 10 files changed, 449 insertions(+), 7 deletions(-)
 create mode 100755 dil/src/main/java/org/assimbly/dil/validation/CertificateRetriever.java
 create mode 100755 dil/src/main/java/org/assimbly/dil/validation/HttpsCertificateValidator.java
 create mode 100755 dil/src/main/java/org/assimbly/dil/validation/https/CompositeTrustManager.java
 create mode 100755 dil/src/main/java/org/assimbly/dil/validation/https/FileBasedTrustStore.java
 create mode 100755 dil/src/main/java/org/assimbly/dil/validation/https/TrustedClientConfigurer.java

diff --git a/dil/src/main/java/org/assimbly/dil/transpiler/ssl/SSLConfiguration.java b/dil/src/main/java/org/assimbly/dil/transpiler/ssl/SSLConfiguration.java
index 29b9ed00..e7b72f4f 100644
--- a/dil/src/main/java/org/assimbly/dil/transpiler/ssl/SSLConfiguration.java
+++ b/dil/src/main/java/org/assimbly/dil/transpiler/ssl/SSLConfiguration.java
@@ -5,6 +5,8 @@
 import org.apache.camel.support.jsse.KeyStoreParameters;
 import org.apache.camel.support.jsse.SSLContextParameters;
 import org.apache.camel.support.jsse.TrustManagersParameters;
+import org.assimbly.dil.validation.HttpsCertificateValidator;
+import org.assimbly.dil.validation.https.FileBasedTrustStore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -15,6 +17,8 @@
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
 import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.Arrays;
 
 
 public class SSLConfiguration {
@@ -91,4 +95,29 @@ public KeyStoreParameters createKeystoreParameters(String keystorePath, String k
 		return keystoreParameters;
 	}
 
+	public void initTrustStoresForHttpsCertificateValidator(
+			String keyStorePath, String keyStorePassword,
+			String trustStorePath, String trustStorePassword){
+
+		try {
+			// init HttpsCertificateValidator
+			FileBasedTrustStore customKeyStore = new FileBasedTrustStore();
+			customKeyStore.setPath(trustStorePath);
+			customKeyStore.setType("jks");
+			customKeyStore.setPassword(trustStorePassword);
+
+			FileBasedTrustStore jreKeyStore = new FileBasedTrustStore();
+			jreKeyStore.setPath(keyStorePath);
+			jreKeyStore.setType("jks");
+			jreKeyStore.setPassword(keyStorePassword);
+
+			HttpsCertificateValidator httpsCertificateValidator = new HttpsCertificateValidator();
+			httpsCertificateValidator.setCustomTrustStore(customKeyStore);
+			httpsCertificateValidator.setTrustStores(new ArrayList(Arrays.asList(customKeyStore, jreKeyStore)));
+		} catch (Exception e) {
+			log.error("Failed to init trust stores for HttpsCertificateValidator",e);
+		}
+
+	}
+
 }
diff --git a/dil/src/main/java/org/assimbly/dil/validation/CertificateRetriever.java b/dil/src/main/java/org/assimbly/dil/validation/CertificateRetriever.java
new file mode 100755
index 00000000..a2138f45
--- /dev/null
+++ b/dil/src/main/java/org/assimbly/dil/validation/CertificateRetriever.java
@@ -0,0 +1,9 @@
+package org.assimbly.dil.validation;
+
+import java.util.List;
+
+public interface CertificateRetriever {
+
+    public void addHttpsCertificatesToTrustStore(List urls) throws Exception;
+
+}
diff --git a/dil/src/main/java/org/assimbly/dil/validation/HttpsCertificateValidator.java b/dil/src/main/java/org/assimbly/dil/validation/HttpsCertificateValidator.java
new file mode 100755
index 00000000..0f2a1538
--- /dev/null
+++ b/dil/src/main/java/org/assimbly/dil/validation/HttpsCertificateValidator.java
@@ -0,0 +1,119 @@
+package org.assimbly.dil.validation;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.HttpHead;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.assimbly.dil.validation.https.FileBasedTrustStore;
+import org.assimbly.dil.validation.https.TrustedClientConfigurer;
+
+import javax.net.ssl.SSLException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class HttpsCertificateValidator implements CertificateRetriever {
+
+    static private List trustStores = new ArrayList<>();
+    static private FileBasedTrustStore customTrustStore;
+    static private HttpClient httpClient;
+
+    /**
+     * Checks if the certificate of the given HTTPS url is valid or not.
+     * 

+ * Valid means the certificate is trusted by the default system truststore or the custom trust store + * Invalid means anything else, from expired certificate to self signed etc. + * + * @return ValidationResult. If a certificate is found invalid or it cannot be determined a message will be included. + */ + public ValidationResult validate(String httpsUrlString) { + if (!httpsUrlString.startsWith("https://")) { + throw new IllegalArgumentException("Provided url " + httpsUrlString + "is not a HTTPS url"); + } + + httpsUrlString = httpsUrlString.replace(" ", "%20"); + + RequestConfig reqConfig = RequestConfig.custom() + .setConnectionRequestTimeout(15000) + .setConnectTimeout(15000) + .setSocketTimeout(15000) + .build(); + + HttpHead req = new HttpHead(httpsUrlString); + req.setConfig(reqConfig); + + try { + HttpResponse response = httpClient.execute(req); + } catch (SSLException e) { + return new ValidationResult(ValidationResultStatus.INVALID, getRootCause(e).getMessage()); + } catch (IOException e) { + return new ValidationResult(ValidationResultStatus.UNKNOWN, getRootCause(e).getMessage()); + } + + return new ValidationResult(ValidationResultStatus.VALID, null); + } + + public void addHttpsCertificatesToTrustStore(List urls) throws Exception { + for (int i = 0; i < urls.size(); i++) { + String url = urls.get(i); + ValidationResult result = validate(url); + if (result.getValidationResultStatus().equals(ValidationResultStatus.INVALID)) { + customTrustStore.addCertificateForHttpsUrl(url); + buildHttpClient(); + } + } + } + + public void setCustomTrustStore(FileBasedTrustStore customTrustStore) { + this.customTrustStore = customTrustStore; + } + + public void setTrustStores(List trustStores) { + this.trustStores = trustStores; + + // When the truststores are updated our http client should be reconfigured as well + // to use the new truststores. + buildHttpClient(); + } + + private void buildHttpClient() { + TrustedClientConfigurer trustedClientConfigurer = new TrustedClientConfigurer(); + trustedClientConfigurer.setTrustStores(trustStores); + + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); + trustedClientConfigurer.configureHttpClient(httpClientBuilder); + + httpClient = httpClientBuilder.build(); + } + + private Throwable getRootCause(Throwable throwable) { + if (throwable.getCause() != null) { + return getRootCause(throwable.getCause()); + } + + return throwable; + } + + public enum ValidationResultStatus { + VALID, INVALID, UNKNOWN + } + + public class ValidationResult { + private final ValidationResultStatus validationResultStatus; + private final String message; + + public ValidationResult(ValidationResultStatus validationResultStatus, String message) { + this.validationResultStatus = validationResultStatus; + this.message = message; + } + + public ValidationResultStatus getValidationResultStatus() { + return validationResultStatus; + } + + public String getMessage() { + return message; + } + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/https/CompositeTrustManager.java b/dil/src/main/java/org/assimbly/dil/validation/https/CompositeTrustManager.java new file mode 100755 index 00000000..a888597b --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/https/CompositeTrustManager.java @@ -0,0 +1,82 @@ +package org.assimbly.dil.validation.https; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CompositeTrustManager implements X509TrustManager { + + private List trustManagers = new ArrayList<>(); + + public void addTrustManagers(KeyStore trustStore) throws KeyStoreException { + try { + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(trustStore); + + for(TrustManager tm: tmf.getTrustManagers()) { + if(tm instanceof X509TrustManager) { + addTrustManager((X509TrustManager) tm); + } + } + } catch (Exception e) { + throw new KeyStoreException(e); + } + } + + public void addTrustManager(X509TrustManager trustManager) { + trustManagers.add(trustManager); + } + + public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { + CertificateException latestException = null; + boolean trusted = false; + + for(X509TrustManager trustManager: trustManagers) { + try { + trustManager.checkClientTrusted(x509Certificates, s); + trusted = true; + } catch(CertificateException cex) { + latestException = cex; + } + } + + if(!trusted) { + throw latestException; + } + } + + public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { + CertificateException latestException = null; + boolean trusted = false; + + for(X509TrustManager trustManager: trustManagers) { + try { + trustManager.checkServerTrusted(x509Certificates, s); + trusted = true; + } catch(CertificateException cex) { + latestException = cex; + } + } + + if(!trusted) { + throw latestException; + } + } + + public X509Certificate[] getAcceptedIssuers() { + List acceptedIssuers = new ArrayList<>(); + + for(X509TrustManager trustManager: trustManagers) { + acceptedIssuers.addAll(Arrays.asList(trustManager.getAcceptedIssuers())); + } + + return acceptedIssuers.toArray(new X509Certificate[acceptedIssuers.size()]); + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/https/FileBasedTrustStore.java b/dil/src/main/java/org/assimbly/dil/validation/https/FileBasedTrustStore.java new file mode 100755 index 00000000..dd73eb44 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/https/FileBasedTrustStore.java @@ -0,0 +1,106 @@ +package org.assimbly.dil.validation.https; + +import org.apache.http.conn.ssl.NoopHostnameVerifier; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.SecureRandom; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; + +public class FileBasedTrustStore { + + private String path; + private String type; + private String password; + + public void setPath(String path) { + this.path = path; + } + + public void setType(String type) { + this.type = type; + } + + public void setPassword(String password) { + this.password = password; + } + + public KeyStore loadTrustStore() throws KeyStoreException, IOException { + try { + KeyStore trustStore = KeyStore.getInstance(type); + trustStore.load(new FileInputStream(path), password.toCharArray()); + + return trustStore; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new KeyStoreException("couldn't load truststore from: " + path, e); + } + } + + public void addCertificateEntry(String alias, Certificate certificate) throws KeyStoreException, IOException { + KeyStore trustStore = loadTrustStore(); + trustStore.setCertificateEntry(alias, certificate); + + try { + synchronized (this) { + trustStore.store(new FileOutputStream(path), password.toCharArray()); + } + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new KeyStoreException("couldn't write to truststore " + path, e); + } + } + + public void addCertificateForHttpsUrl(String url) throws Exception { + HttpsURLConnection conn = getUnsecuredConnection(url); + conn.connect(); + Certificate[] certs = conn.getServerCertificates(); + + for (Certificate cert : certs) { + if (cert instanceof X509Certificate) { + X509Certificate x509 = ((X509Certificate) cert); + this.addCertificateEntry(String.valueOf(x509.getSerialNumber()), x509); + } else { + throw new Exception("unknown certificate type " + cert); + } + } + } + + private HttpsURLConnection getUnsecuredConnection(String url) throws Exception { + URL destinationURL = new URL(url); + HttpsURLConnection conn = (HttpsURLConnection) destinationURL.openConnection(); + SSLContext ctx = SSLContext.getInstance("TLS"); + ctx.init(null, new TrustManager[]{insecureTrustManager()}, new SecureRandom()); + conn.setSSLSocketFactory(ctx.getSocketFactory()); + conn.setHostnameVerifier(new NoopHostnameVerifier()); + return conn; + } + + private static TrustManager insecureTrustManager() { + return new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + } + }; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/https/TrustedClientConfigurer.java b/dil/src/main/java/org/assimbly/dil/validation/https/TrustedClientConfigurer.java new file mode 100755 index 00000000..be2bd291 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/https/TrustedClientConfigurer.java @@ -0,0 +1,60 @@ +package org.assimbly.dil.validation.https; + +import org.apache.camel.component.http.HttpClientConfigurer; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import java.util.ArrayList; +import java.util.List; + +public class TrustedClientConfigurer implements HttpClientConfigurer { + + private static Logger logger = LoggerFactory.getLogger(TrustedClientConfigurer.class); + + private List trustStores = new ArrayList<>(); + + @Override + public void configureHttpClient(HttpClientBuilder clientBuilder) { + CompositeTrustManager compositeTrustManager = new CompositeTrustManager(); + + try { + for(FileBasedTrustStore trustStore: trustStores) { + compositeTrustManager.addTrustManagers(trustStore.loadTrustStore()); + } + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, new TrustManager[] { compositeTrustManager }, null); + + SSLConnectionSocketFactory sslConnectionFactory = + new SSLConnectionSocketFactory(sslContext, new DefaultHostnameVerifier()); + + clientBuilder.setSSLContext(sslContext); + clientBuilder.setSSLSocketFactory(sslConnectionFactory); + + Registry registry = RegistryBuilder.create() + .register("https", sslConnectionFactory) + .build(); + + PoolingHttpClientConnectionManager ccm = new PoolingHttpClientConnectionManager(registry); + clientBuilder.setConnectionManager(ccm); + + logger.info("Setup SSL context for https4 scheme"); + } catch (Exception e) { + logger.error("Failed to setup SSL context", e); + throw new RuntimeException(e); + } + } + + public void setTrustStores(List trustStores) { + this.trustStores = trustStores; + } +} diff --git a/integration/src/main/java/org/assimbly/integration/Integration.java b/integration/src/main/java/org/assimbly/integration/Integration.java index b67d6d90..69d02adf 100644 --- a/integration/src/main/java/org/assimbly/integration/Integration.java +++ b/integration/src/main/java/org/assimbly/integration/Integration.java @@ -4,6 +4,7 @@ import org.apache.camel.ConsumerTemplate; import org.apache.camel.ProducerTemplate; import org.apache.camel.spi.EventNotifier; +import org.assimbly.dil.validation.HttpsCertificateValidator; import org.assimbly.dil.validation.beans.Expression; import org.assimbly.dil.validation.beans.FtpSettings; import org.assimbly.dil.validation.beans.Regex; @@ -838,7 +839,7 @@ public interface Integration { * * @param certificate * @return result of validation */ - public String validateCertificate(String certificate); + public HttpsCertificateValidator.ValidationResult validateCertificate(String httpsUrl); /** * Validates a url expression diff --git a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java index 2508d1a1..95cafd45 100644 --- a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java +++ b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java @@ -4,6 +4,7 @@ import org.apache.camel.ConsumerTemplate; import org.apache.camel.ProducerTemplate; import org.apache.camel.spi.EventNotifier; +import org.assimbly.dil.validation.HttpsCertificateValidator; import org.assimbly.dil.validation.beans.Expression; import org.assimbly.dil.validation.beans.FtpSettings; import org.assimbly.dil.validation.beans.Regex; @@ -409,7 +410,7 @@ public String testConnection(String host, int port, int timeOut) { public abstract ValidationErrorMessage validateCron(String cronExpression); - public abstract String validateCertificate(String certificate); + public abstract HttpsCertificateValidator.ValidationResult validateCertificate(String httpsUrl); public abstract ValidationErrorMessage validateUrl(String url); diff --git a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java index 2fe8f517..ef763405 100644 --- a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java +++ b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java @@ -34,6 +34,7 @@ import org.assimbly.dil.validation.*; import org.assimbly.dil.validation.beans.FtpSettings; import org.assimbly.dil.validation.beans.Regex; +import org.assimbly.dil.validation.https.FileBasedTrustStore; import org.assimbly.docconverter.DocConverter; import org.assimbly.integration.loader.ConnectorRoute; import org.assimbly.dil.loader.FlowLoader; @@ -1961,8 +1962,16 @@ public ValidationErrorMessage validateCron(String cronExpression) { } @Override - public String validateCertificate(String certificate) { - return null; + public HttpsCertificateValidator.ValidationResult validateCertificate(String httpsUrl) { + HttpsCertificateValidator httpsCertificateValidator = new HttpsCertificateValidator(); + try { + List urlList = new ArrayList<>(); + urlList.add(httpsUrl); + httpsCertificateValidator.addHttpsCertificatesToTrustStore(urlList); + } catch (Exception e) { + System.out.println("Error to add certificate: " + e.getMessage()); + } + return httpsCertificateValidator.validate(httpsUrl); } @Override @@ -2042,6 +2051,8 @@ private void setSSLContext() throws Exception { for (String sslComponent : sslComponents) { sslConfiguration.setUseGlobalSslContextParameters(context, sslComponent); } + + sslConfiguration.initTrustStoresForHttpsCertificateValidator(keyStorePath, "supersecret", trustStorePath, "supersecret"); } /** diff --git a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java index 206f6f45..0b7a26dc 100644 --- a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java +++ b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java @@ -3,12 +3,14 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.Parameter; +import org.assimbly.dil.validation.HttpsCertificateValidator; import org.assimbly.dil.validation.beans.Expression; import org.assimbly.dil.validation.beans.FtpSettings; import org.assimbly.dil.validation.beans.Regex; import org.assimbly.integration.Integration; import org.assimbly.util.error.ValidationErrorMessage; import org.assimbly.util.rest.ResponseUtil; +import org.eclipse.jetty.util.security.CertificateValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -33,6 +35,8 @@ public class ValidationResource { @Autowired private IntegrationResource integrationResource; + private boolean plainResponse; + private Integration integration; //validations @@ -65,13 +69,33 @@ public ResponseEntity validateCron( } @GetMapping(path = "/validation/{integrationId}/certificate", produces = {"application/xml","application/json","text/plain"}) - public ResponseEntity validateCertificate(@Parameter(hidden = true) @RequestHeader("Accept") String mediaType, @PathVariable Long integrationId) throws Exception { + public ResponseEntity validateCertificate( + @Parameter(hidden = true) @RequestHeader("Accept") String mediaType, + @Parameter String httpsUrl, + @PathVariable Long integrationId + ) throws Exception { - try { + plainResponse = true; + try { integration = integrationResource.getIntegration(); - return ResponseUtil.createSuccessResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/certificate", "", "", ""); + HttpsCertificateValidator.ValidationResult certificateResp = integration.validateCertificate(httpsUrl); + + if(certificateResp!=null) { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(out, certificateResp); + if(certificateResp.getValidationResultStatus().equals(HttpsCertificateValidator.ValidationResultStatus.VALID)) { + // return code 304 + return ResponseUtil.createNotModifiedResponse(integrationId, "/validation/{integrationId}/certificate"); + } else { + // return code 200 + return ResponseUtil.createSuccessResponse(integrationId, mediaType, "/validation/{integrationId}/certificate", out.toString(), plainResponse); + } + } else { + return ResponseUtil.createSuccessResponse(integrationId, mediaType, "/validation/{integrationId}/certificate", "", plainResponse); + } } catch (Exception e) { log.error("ErrorMessage",e); return ResponseUtil.createFailureResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/certificate", e.getMessage(), "",""); From ef667d10ecc85c66b861662f8e0b38b4b49010da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Gon=C3=A7alves?= Date: Wed, 11 Jan 2023 15:23:24 +0000 Subject: [PATCH 08/11] scripts endpoint --- dil/pom.xml | 17 +++++ .../dil/validation/ScriptValidator.java | 74 +++++++++++++++++++ .../beans/script/BadRequestResponse.java | 22 ++++++ .../beans/script/EvaluationRequest.java | 32 ++++++++ .../beans/script/EvaluationResponse.java | 44 +++++++++++ .../validation/beans/script/ExchangeDto.java | 45 +++++++++++ .../validation/beans/script/ScriptDto.java | 33 +++++++++ .../scripts/ExchangeMarshaller.java | 59 +++++++++++++++ .../org/assimbly/integration/Integration.java | 4 +- .../integration/impl/BaseIntegration.java | 4 +- .../integration/impl/CamelIntegration.java | 8 +- .../integrationrest/ValidationResource.java | 37 +++++++++- 12 files changed, 371 insertions(+), 8 deletions(-) create mode 100755 dil/src/main/java/org/assimbly/dil/validation/ScriptValidator.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/beans/script/BadRequestResponse.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/beans/script/EvaluationRequest.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/beans/script/EvaluationResponse.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/beans/script/ExchangeDto.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/beans/script/ScriptDto.java create mode 100644 dil/src/main/java/org/assimbly/dil/validation/scripts/ExchangeMarshaller.java diff --git a/dil/pom.xml b/dil/pom.xml index 76fffbf6..658a9722 100644 --- a/dil/pom.xml +++ b/dil/pom.xml @@ -78,6 +78,23 @@ commons-net ${commons-net.version} + + + org.apache.camel + camel-groovy + 3.20.1 + + + org.apache.camel + camel-javascript + 3.20.1 + + + org.apache.camel + camel-support + 3.20.1 + + diff --git a/dil/src/main/java/org/assimbly/dil/validation/ScriptValidator.java b/dil/src/main/java/org/assimbly/dil/validation/ScriptValidator.java new file mode 100755 index 00000000..147d9fef --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/ScriptValidator.java @@ -0,0 +1,74 @@ +package org.assimbly.dil.validation; + +import org.apache.camel.Exchange; +import org.apache.camel.language.groovy.GroovyExpression; +import org.apache.camel.language.js.JavaScriptExpression; +import org.assimbly.dil.validation.beans.script.EvaluationRequest; +import org.assimbly.dil.validation.beans.script.EvaluationResponse; +import org.assimbly.dil.validation.beans.script.ExchangeDto; +import org.assimbly.dil.validation.beans.script.ScriptDto; +import org.assimbly.dil.validation.scripts.ExchangeMarshaller; + +public class ScriptValidator { + + public EvaluationResponse validate(EvaluationRequest evaluationRequest) { + + if (evaluationRequest == null) { + return createBadRequestResponse(null,"Empty requests aren't allowed"); + } + if (evaluationRequest.getScript() == null || evaluationRequest.getExchange() == null) { + return createBadRequestResponse(evaluationRequest.getExchange(),"Empty requests aren't allowed"); + } + + ScriptDto scriptDto = evaluationRequest.getScript(); + + if (scriptDto.getScript() == null) { + return createBadRequestResponse(evaluationRequest.getExchange(), "Script body cannot be null"); + } + + try { + switch(scriptDto.getLanguage()) { + case "js": + return validateJavaScript(evaluationRequest.getExchange(), scriptDto.getScript()); + case "groovy": + return validateGroovyScript(evaluationRequest.getExchange(), scriptDto.getScript()); + default: + return createBadRequestResponse(evaluationRequest.getExchange(), "Unsupported scripting language"); + } + } catch (Exception e) { + return createBadRequestResponse(evaluationRequest.getExchange(), "Invalid script: '" + e.getMessage() + "'"); + } + } + + private EvaluationResponse validateGroovyScript(ExchangeDto exchangeDto, String script) { + try { + GroovyExpression groovyExpression = new GroovyExpression(script); + Exchange exchangeRequest = ExchangeMarshaller.unmarshall(exchangeDto); + Object response = groovyExpression.evaluate(exchangeRequest, String.class); + ExchangeDto exchangeDtoResponse = ExchangeMarshaller.marshall(exchangeRequest); + return createOKRequestResponse(exchangeDtoResponse, String.valueOf(response)); + } catch (Exception e) { + return createBadRequestResponse(exchangeDto, "Invalid groovy script: '" + e.getMessage() + "'"); + } + } + + private EvaluationResponse validateJavaScript(ExchangeDto exchangeDto, String script) { + try { + JavaScriptExpression javaScriptEvaluator = new JavaScriptExpression(script, String.class); + Exchange exchangeRequest = ExchangeMarshaller.unmarshall(exchangeDto); + Object response = javaScriptEvaluator.evaluate(exchangeRequest, String.class); + ExchangeDto exchangeDtoResponse = ExchangeMarshaller.marshall(exchangeRequest); + return createOKRequestResponse(exchangeDtoResponse, String.valueOf(response)); + } catch (Exception e) { + return createBadRequestResponse(exchangeDto, "Invalid javascript: '" + e.getMessage() + "'"); + } + } + + private EvaluationResponse createOKRequestResponse(ExchangeDto exchange, String message) { + return new EvaluationResponse(exchange, message, 1); + } + + private EvaluationResponse createBadRequestResponse(ExchangeDto exchange, String message) { + return new EvaluationResponse(exchange, message, -1); + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/beans/script/BadRequestResponse.java b/dil/src/main/java/org/assimbly/dil/validation/beans/script/BadRequestResponse.java new file mode 100644 index 00000000..adebde52 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/beans/script/BadRequestResponse.java @@ -0,0 +1,22 @@ +package org.assimbly.dil.validation.beans.script; + +public class BadRequestResponse { + + private String message; + + @SuppressWarnings("unused") + protected BadRequestResponse() {} + + public BadRequestResponse(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + @SuppressWarnings("unused") + protected void setMessage(String message) { + this.message = message; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/beans/script/EvaluationRequest.java b/dil/src/main/java/org/assimbly/dil/validation/beans/script/EvaluationRequest.java new file mode 100644 index 00000000..9dcf1ad6 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/beans/script/EvaluationRequest.java @@ -0,0 +1,32 @@ +package org.assimbly.dil.validation.beans.script; + +public class EvaluationRequest { + + private ExchangeDto exchange; + private ScriptDto script; + + @SuppressWarnings("unused") + protected EvaluationRequest() {} + + public EvaluationRequest(ExchangeDto exchange, ScriptDto script) { + this.exchange= exchange; + this.script = script; + } + public ExchangeDto getExchange() { + return exchange; + } + + @SuppressWarnings("unused") + protected void setExchange(ExchangeDto exchange) { + this.exchange = exchange; + } + + public ScriptDto getScript() { + return script; + } + + @SuppressWarnings("unused") + protected void setScript(ScriptDto script) { + this.script = script; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/beans/script/EvaluationResponse.java b/dil/src/main/java/org/assimbly/dil/validation/beans/script/EvaluationResponse.java new file mode 100644 index 00000000..995ca614 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/beans/script/EvaluationResponse.java @@ -0,0 +1,44 @@ +package org.assimbly.dil.validation.beans.script; + +public class EvaluationResponse { + + private ExchangeDto exchange; + private String result; + private int code; + + @SuppressWarnings("unused") + protected EvaluationResponse() {} + + public EvaluationResponse(ExchangeDto exchange, String result, int code) { + this.exchange = exchange; + this.result = result; + this.code = code; + } + + public ExchangeDto getExchange() { + return exchange; + } + + @SuppressWarnings("unused") + protected void setExchange(ExchangeDto exchange) { + this.exchange = exchange; + } + + public String getResult() { + return result; + } + + @SuppressWarnings("unused") + protected void setResult(String result) { + this.result = result; + } + + public int getCode() { + return code; + } + + @SuppressWarnings("unused") + public void setCode(int code) { + this.code = code; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/beans/script/ExchangeDto.java b/dil/src/main/java/org/assimbly/dil/validation/beans/script/ExchangeDto.java new file mode 100644 index 00000000..0511d9d4 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/beans/script/ExchangeDto.java @@ -0,0 +1,45 @@ +package org.assimbly.dil.validation.beans.script; + +import java.util.Map; + +public class ExchangeDto { + + private Map properties; + private Map headers; + private String body; + + public ExchangeDto() {} + + public ExchangeDto(Map properties, Map headers, String body) { + this.properties = properties; + this.headers = headers; + this.body = body; + } + + public Map getProperties() { + return properties; + } + + @SuppressWarnings("unused") + protected void setProperties(Map properties) { + this.properties = properties; + } + + public Map getHeaders() { + return headers; + } + + @SuppressWarnings("unused") + protected void setHeaders(Map headers) { + this.headers = headers; + } + + public String getBody() { + return body; + } + + @SuppressWarnings("unused") + protected void setBody(String body) { + this.body = body; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/beans/script/ScriptDto.java b/dil/src/main/java/org/assimbly/dil/validation/beans/script/ScriptDto.java new file mode 100644 index 00000000..b0807f27 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/beans/script/ScriptDto.java @@ -0,0 +1,33 @@ +package org.assimbly.dil.validation.beans.script; + +public class ScriptDto { + + private String language; + private String script; + + @SuppressWarnings("unused") + protected ScriptDto() {} + + public ScriptDto(String language, String script) { + this.language = language; + this.script = script; + } + + public String getLanguage() { + return language; + } + + @SuppressWarnings("unused") + protected void setLanguage(String language) { + this.language = language; + } + + public String getScript() { + return script; + } + + @SuppressWarnings("unused") + protected void setScript(String script) { + this.script = script; + } +} diff --git a/dil/src/main/java/org/assimbly/dil/validation/scripts/ExchangeMarshaller.java b/dil/src/main/java/org/assimbly/dil/validation/scripts/ExchangeMarshaller.java new file mode 100644 index 00000000..b7b52199 --- /dev/null +++ b/dil/src/main/java/org/assimbly/dil/validation/scripts/ExchangeMarshaller.java @@ -0,0 +1,59 @@ +package org.assimbly.dil.validation.scripts; + +import org.apache.camel.Exchange; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.support.DefaultExchange; +import org.assimbly.dil.validation.beans.script.ExchangeDto; + +import java.util.HashMap; +import java.util.Map; + +public class ExchangeMarshaller { + public static Exchange unmarshall(ExchangeDto exchangeDto) { + Exchange exchange = new DefaultExchange(new DefaultCamelContext()); + + if (exchangeDto.getBody() != null) { + System.out.println("body: "+exchangeDto.getBody()); + exchange.getIn().setBody(exchangeDto.getBody()); + } + + if (exchangeDto.getHeaders() != null) { + for (Map.Entry entry : exchangeDto.getHeaders().entrySet()) { + System.out.println("header: "+entry.getKey()+", "+entry.getValue()); + exchange.getIn().setHeader(entry.getKey(), entry.getValue()); + } + } + + if (exchangeDto.getProperties() != null) { + for (Map.Entry entry : exchangeDto.getProperties().entrySet()) { + System.out.println("property: "+entry.getKey()+", "+entry.getValue()); + exchange.setProperty(entry.getKey(), entry.getValue()); + } + } + + return exchange; + } + + public static ExchangeDto marshall(Exchange exchange) { + String body = null; + if (exchange.getIn().getBody() != null) { + body = exchange.getIn().getBody(String.class); + } + + Map headers = new HashMap<>(); + if (exchange.getIn().getHeaders() != null) { + for (String key : exchange.getIn().getHeaders().keySet()) { + headers.put(key, exchange.getIn().getHeader(key, String.class)); + } + } + + Map properties = new HashMap<>(); + if (exchange.getProperties() != null) { + for (String key : exchange.getProperties().keySet()) { + properties.put(key, exchange.getProperty(key, String.class)); + } + } + + return new ExchangeDto(properties, headers, body); + } +} diff --git a/integration/src/main/java/org/assimbly/integration/Integration.java b/integration/src/main/java/org/assimbly/integration/Integration.java index 69d02adf..29c6a68a 100644 --- a/integration/src/main/java/org/assimbly/integration/Integration.java +++ b/integration/src/main/java/org/assimbly/integration/Integration.java @@ -8,6 +8,8 @@ import org.assimbly.dil.validation.beans.Expression; import org.assimbly.dil.validation.beans.FtpSettings; import org.assimbly.dil.validation.beans.Regex; +import org.assimbly.dil.validation.beans.script.EvaluationRequest; +import org.assimbly.dil.validation.beans.script.EvaluationResponse; import org.assimbly.util.EncryptionUtil; import org.assimbly.util.error.ValidationErrorMessage; @@ -879,6 +881,6 @@ public interface Integration { * @param script the script (for example Groovy) * @return result of validation */ - public String validateScript(String script); + public EvaluationResponse validateScript(EvaluationRequest scriptRequest); } \ No newline at end of file diff --git a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java index 95cafd45..47942cb7 100644 --- a/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java +++ b/integration/src/main/java/org/assimbly/integration/impl/BaseIntegration.java @@ -8,6 +8,8 @@ import org.assimbly.dil.validation.beans.Expression; import org.assimbly.dil.validation.beans.FtpSettings; import org.assimbly.dil.validation.beans.Regex; +import org.assimbly.dil.validation.beans.script.EvaluationRequest; +import org.assimbly.dil.validation.beans.script.EvaluationResponse; import org.assimbly.integration.Integration; import org.assimbly.dil.transpiler.JSONFileConfiguration; import org.assimbly.dil.transpiler.XMLFileConfiguration; @@ -420,6 +422,6 @@ public String testConnection(String host, int port, int timeOut) { public abstract AbstractMap.SimpleEntry validateRegex(Regex regex); - public abstract String validateScript(String script); + public abstract EvaluationResponse validateScript(EvaluationRequest scriptRequest); } diff --git a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java index ef763405..31a9e8b2 100644 --- a/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java +++ b/integration/src/main/java/org/assimbly/integration/impl/CamelIntegration.java @@ -34,6 +34,8 @@ import org.assimbly.dil.validation.*; import org.assimbly.dil.validation.beans.FtpSettings; import org.assimbly.dil.validation.beans.Regex; +import org.assimbly.dil.validation.beans.script.EvaluationRequest; +import org.assimbly.dil.validation.beans.script.EvaluationResponse; import org.assimbly.dil.validation.https.FileBasedTrustStore; import org.assimbly.docconverter.DocConverter; import org.assimbly.integration.loader.ConnectorRoute; @@ -52,6 +54,7 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.core.type.filter.RegexPatternTypeFilter; +import org.springframework.scripting.ScriptEvaluator; import org.w3c.dom.Document; import javax.xml.xpath.XPath; @@ -1999,8 +2002,9 @@ public AbstractMap.SimpleEntry validateRegex(Regex regex) { } @Override - public String validateScript(String script) { - return null; + public EvaluationResponse validateScript(EvaluationRequest scriptRequest) { + ScriptValidator scriptValidator = new ScriptValidator(); + return scriptValidator.validate(scriptRequest); } public void setEncryptionProperties(Properties encryptionProperties) { diff --git a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java index 0b7a26dc..ef0058f3 100644 --- a/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java +++ b/integrationRest/src/main/java/org/assimbly/integrationrest/ValidationResource.java @@ -7,6 +7,9 @@ import org.assimbly.dil.validation.beans.Expression; import org.assimbly.dil.validation.beans.FtpSettings; import org.assimbly.dil.validation.beans.Regex; +import org.assimbly.dil.validation.beans.script.BadRequestResponse; +import org.assimbly.dil.validation.beans.script.EvaluationRequest; +import org.assimbly.dil.validation.beans.script.EvaluationResponse; import org.assimbly.integration.Integration; import org.assimbly.util.error.ValidationErrorMessage; import org.assimbly.util.rest.ResponseUtil; @@ -236,16 +239,42 @@ public ResponseEntity validateRegex( } @PostMapping(path = "/validation/{integrationId}/script", consumes = {"application/json"}, produces = {"application/xml","application/json","text/plain"}) - public ResponseEntity validateScript(@Parameter(hidden = true) @RequestHeader("Accept") String mediaType, @RequestHeader(value = "StopTest", defaultValue = "false") boolean stopTest, @PathVariable Long integrationId, @RequestBody String body) throws Exception { + public ResponseEntity validateScript( + @Parameter(hidden = true) @RequestHeader("Accept") String mediaType, + @RequestHeader(value = "StopTest", defaultValue = "false") boolean stopTest, + @PathVariable Long integrationId, + @RequestBody String body + ) throws Exception { - try { + plainResponse = true; + try { integration = integrationResource.getIntegration(); - return ResponseUtil.createSuccessResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/script", "", "", ""); + EvaluationRequest scriptRequest = null; + if(body!=null){ + scriptRequest = new ObjectMapper().readValue(body, EvaluationRequest.class); + } + + EvaluationResponse scriptResp = integration.validateScript(scriptRequest); + + if(scriptResp!=null) { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final ObjectMapper mapper = new ObjectMapper(); + if(scriptResp.getCode() == 1) { + mapper.writeValue(out, scriptResp); + return ResponseUtil.createSuccessResponse(integrationId, mediaType, "/validation/{integrationId}/script", out.toString(), plainResponse); + } else { + mapper.writeValue(out, new BadRequestResponse(scriptResp.getResult())); + return ResponseUtil.createFailureResponse(integrationId, mediaType, "/validation/{integrationId}/script", out.toString(), plainResponse); + } + } else { + return ResponseUtil.createFailureResponse(integrationId, mediaType, "/validation/{integrationId}/script", "", plainResponse); + } + } catch (Exception e) { log.error("Error",e); - return ResponseUtil.createFailureResponseWithHeaders(integrationId, mediaType, "/validation/{integrationId}/script", e.getMessage(), "", ""); + return ResponseUtil.createFailureResponse(integrationId, mediaType, "/validation/{integrationId}/script", e.getMessage(), plainResponse); } } From c151ed4de1ec27c4ceee963645209c22e5b2a20c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Gon=C3=A7alves?= Date: Wed, 11 Jan 2023 15:45:00 +0000 Subject: [PATCH 09/11] removed scope tag --- dil/pom.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dil/pom.xml b/dil/pom.xml index 658a9722..ff8fe540 100644 --- a/dil/pom.xml +++ b/dil/pom.xml @@ -41,7 +41,6 @@ org.assimbly test-base ${assimbly.version} - test org.assimbly @@ -53,19 +52,16 @@ org.codehaus.groovy groovy ${groovy-script.version} - provided org.codehaus.groovy groovy-jsr223 ${groovy-script.version} - provided org.codehaus.groovy groovy-dateutil ${groovy-script.version} - provided From 13789343d0a1a22b62c3c151e0135f866a159b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Gon=C3=A7alves?= Date: Wed, 11 Jan 2023 16:33:48 +0000 Subject: [PATCH 10/11] removed some system.out.println lines --- .../assimbly/dil/validation/scripts/ExchangeMarshaller.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/dil/src/main/java/org/assimbly/dil/validation/scripts/ExchangeMarshaller.java b/dil/src/main/java/org/assimbly/dil/validation/scripts/ExchangeMarshaller.java index b7b52199..c9883adf 100644 --- a/dil/src/main/java/org/assimbly/dil/validation/scripts/ExchangeMarshaller.java +++ b/dil/src/main/java/org/assimbly/dil/validation/scripts/ExchangeMarshaller.java @@ -13,20 +13,17 @@ public static Exchange unmarshall(ExchangeDto exchangeDto) { Exchange exchange = new DefaultExchange(new DefaultCamelContext()); if (exchangeDto.getBody() != null) { - System.out.println("body: "+exchangeDto.getBody()); exchange.getIn().setBody(exchangeDto.getBody()); } if (exchangeDto.getHeaders() != null) { for (Map.Entry entry : exchangeDto.getHeaders().entrySet()) { - System.out.println("header: "+entry.getKey()+", "+entry.getValue()); exchange.getIn().setHeader(entry.getKey(), entry.getValue()); } } if (exchangeDto.getProperties() != null) { for (Map.Entry entry : exchangeDto.getProperties().entrySet()) { - System.out.println("property: "+entry.getKey()+", "+entry.getValue()); exchange.setProperty(entry.getKey(), entry.getValue()); } } From 1b27ad719fef3a6511ddd0db7f5743b1b06335c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Gon=C3=A7alves?= Date: Wed, 11 Jan 2023 17:20:20 +0000 Subject: [PATCH 11/11] refactoring the pom files --- broker/pom.xml | 2 +- brokerRest/pom.xml | 2 +- dil/pom.xml | 57 +++++++---------------------------------- integration/pom.xml | 2 +- integrationRest/pom.xml | 2 +- pom.xml | 8 ++---- 6 files changed, 15 insertions(+), 58 deletions(-) diff --git a/broker/pom.xml b/broker/pom.xml index 221a7b3f..ab59703e 100644 --- a/broker/pom.xml +++ b/broker/pom.xml @@ -6,7 +6,7 @@ runtime org.assimbly - 3.8.1 + 3.8.2 broker diff --git a/brokerRest/pom.xml b/brokerRest/pom.xml index 1b7e62cb..f5a0e52c 100644 --- a/brokerRest/pom.xml +++ b/brokerRest/pom.xml @@ -6,7 +6,7 @@ runtime org.assimbly - 3.8.1 + 3.8.2 broker-rest diff --git a/dil/pom.xml b/dil/pom.xml index ff8fe540..be297967 100644 --- a/dil/pom.xml +++ b/dil/pom.xml @@ -4,7 +4,7 @@ runtime org.assimbly - 3.8.1 + 3.8.2 dil @@ -28,9 +28,14 @@ - org.assimbly - camel-base - ${assimbly.version} + org.assimbly + camel-base + ${assimbly.version} + + + org.assimbly + camel-components + ${assimbly.version} org.assimbly @@ -47,50 +52,6 @@ utils ${assimbly.version} - - - org.codehaus.groovy - groovy - ${groovy-script.version} - - - org.codehaus.groovy - groovy-jsr223 - ${groovy-script.version} - - - org.codehaus.groovy - groovy-dateutil - ${groovy-script.version} - - - - org.apache.servicemix.bundles - org.apache.servicemix.bundles.jsch - ${jsch.version} - - - commons-net - commons-net - ${commons-net.version} - - - - org.apache.camel - camel-groovy - 3.20.1 - - - org.apache.camel - camel-javascript - 3.20.1 - - - org.apache.camel - camel-support - 3.20.1 - - diff --git a/integration/pom.xml b/integration/pom.xml index 35a85bc3..f145e123 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -4,7 +4,7 @@ runtime org.assimbly - 3.8.1 + 3.8.2 integration diff --git a/integrationRest/pom.xml b/integrationRest/pom.xml index 5647e8f5..72d805f2 100644 --- a/integrationRest/pom.xml +++ b/integrationRest/pom.xml @@ -6,7 +6,7 @@ runtime org.assimbly - 3.8.1 + 3.8.2 integration-rest diff --git a/pom.xml b/pom.xml index 2bf569a0..3eb03145 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ org.assimbly runtime - 3.8.1 + 3.8.2 broker @@ -25,14 +25,10 @@ UTF-8 ${project.basedir} - 3.8.1 + 3.8.2 4.2.13 - 2.5.4 1.7.1 1.6.13 - - 3.6 - 0.1.48_1