diff --git a/pom.xml b/pom.xml
index 5936da5c..541441bd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,7 +60,7 @@
3.2.0
- 2.1.5.RELEASE
+ 2.1.8.RELEASE
2.9.0
UTF-8
diff --git a/scb-engine/pom.xml b/scb-engine/pom.xml
index a7c8bce5..c01a6212 100644
--- a/scb-engine/pom.xml
+++ b/scb-engine/pom.xml
@@ -95,6 +95,11 @@
camunda-bpm-spring-boot-starter-test
test
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jdk8
+
diff --git a/scb-engine/src/main/java/io/securecodebox/engine/execution/DefaultScanProcessExecution.java b/scb-engine/src/main/java/io/securecodebox/engine/execution/DefaultScanProcessExecution.java
index ce6be858..518f0b57 100644
--- a/scb-engine/src/main/java/io/securecodebox/engine/execution/DefaultScanProcessExecution.java
+++ b/scb-engine/src/main/java/io/securecodebox/engine/execution/DefaultScanProcessExecution.java
@@ -20,16 +20,13 @@
package io.securecodebox.engine.execution;
import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import io.securecodebox.constants.DefaultFields;
-import io.securecodebox.model.rest.Report;
+import io.securecodebox.engine.service.ExecutionTimeService;
import io.securecodebox.model.execution.ScanProcessExecution;
import io.securecodebox.model.execution.Scanner;
import io.securecodebox.model.execution.Target;
import io.securecodebox.model.findings.Finding;
import io.securecodebox.scanprocess.ProcessVariableHelper;
-import java.util.Map;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.variable.value.BooleanValue;
import org.camunda.bpm.engine.variable.value.StringValue;
@@ -37,8 +34,11 @@
import org.springframework.util.StringUtils;
import java.util.Collections;
+import java.util.Date;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import java.util.UUID;
/**
@@ -51,8 +51,12 @@ public class DefaultScanProcessExecution implements ScanProcessExecution {
@JsonIgnore
protected DelegateExecution execution;
+ @JsonIgnore
+ public ExecutionTimeService executionTimeService;
+
public DefaultScanProcessExecution(DelegateExecution execution) {
this.execution = execution;
+ this.executionTimeService = new ExecutionTimeService(execution);
}
@Override
@@ -166,7 +170,7 @@ public boolean isAutomated() {
}
@Override
- public String getScannerType(){
+ public String getScannerType() {
return (String) execution.getVariable(DefaultFields.PROCESS_SCANNER_TYPE.name());
}
@@ -175,7 +179,7 @@ public String getScannerType(){
* Same as the Name of the securityTest. e.g. nmap
*/
@Override
- public String getName(){
+ public String getName() {
return (String) execution.getVariable(DefaultFields.PROCESS_NAME.name());
}
@@ -189,7 +193,28 @@ public void setName(String name) {
}
@Override
- public Map getMetaData(){
+ public Map getMetaData() {
return (Map) execution.getVariable(DefaultFields.PROCESS_META_DATA.name());
}
+
+ @Override
+ public Date getStartDate(){
+ return executionTimeService.getStartDate();
+ }
+
+ @Override
+ public Optional getEndDate(){
+ return executionTimeService.getEndDate();
+ }
+
+ @Override
+ public Long getDurationInMilliSeconds() {
+ Date startTime = getStartDate();
+
+ if(startTime == null){
+ return null;
+ }
+
+ return getEndDate().orElseGet(Date::new).getTime() - startTime.getTime();
+ }
}
diff --git a/scb-engine/src/main/java/io/securecodebox/engine/service/ExecutionTimeService.java b/scb-engine/src/main/java/io/securecodebox/engine/service/ExecutionTimeService.java
new file mode 100644
index 00000000..f6118e32
--- /dev/null
+++ b/scb-engine/src/main/java/io/securecodebox/engine/service/ExecutionTimeService.java
@@ -0,0 +1,40 @@
+package io.securecodebox.engine.service;
+
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.camunda.bpm.engine.history.HistoricProcessInstance;
+
+import java.util.Date;
+import java.util.Optional;
+
+public class ExecutionTimeService {
+
+ private DelegateExecution execution;
+
+ public ExecutionTimeService(DelegateExecution execution){
+ this.execution = execution;
+ }
+
+ private Optional getHistoricProcessInstance(){
+ return execution.getProcessEngineServices()
+ .getHistoryService()
+ .createHistoricProcessInstanceQuery()
+ .processInstanceId(execution.getProcessInstanceId())
+ .list()
+ .stream()
+ .findFirst();
+ }
+
+ public Date getStartDate(){
+ return getHistoricProcessInstance()
+ .orElseThrow(() -> new RuntimeException("Failed to finding process"))
+ .getStartTime();
+ }
+
+ public Optional getEndDate(){
+ return Optional.ofNullable(
+ getHistoricProcessInstance()
+ .orElseThrow(() -> new RuntimeException("Failed to finding process"))
+ .getEndTime()
+ );
+ }
+}
diff --git a/scb-engine/src/main/java/io/securecodebox/engine/service/SecurityTestService.java b/scb-engine/src/main/java/io/securecodebox/engine/service/SecurityTestService.java
index 37424a15..cc5d21e0 100644
--- a/scb-engine/src/main/java/io/securecodebox/engine/service/SecurityTestService.java
+++ b/scb-engine/src/main/java/io/securecodebox/engine/service/SecurityTestService.java
@@ -39,6 +39,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -143,7 +144,7 @@ public SecurityTest getCompletedSecurityTest(UUID id) throws SecurityTestNotFoun
List targets = getListValue(variables, DefaultFields.PROCESS_TARGETS, Target.class);
Map metaData = (Map) variables.get(DefaultFields.PROCESS_META_DATA.name()).getValue();
- return new SecurityTest(id, context, name, targets.get(0), report, metaData, tenant);
+ return new SecurityTest(id, context, name, targets.get(0), report, metaData, tenant, process.getStartTime(), Optional.ofNullable(process.getEndTime()));
}
private List getListValue(Map variables, DefaultFields name, Class type) {
diff --git a/scb-engine/src/test/java/io/securecodebox/engine/execution/DefaultScanProcessExecutionTest.java b/scb-engine/src/test/java/io/securecodebox/engine/execution/DefaultScanProcessExecutionTest.java
index 49208255..a375380f 100644
--- a/scb-engine/src/test/java/io/securecodebox/engine/execution/DefaultScanProcessExecutionTest.java
+++ b/scb-engine/src/test/java/io/securecodebox/engine/execution/DefaultScanProcessExecutionTest.java
@@ -20,8 +20,10 @@
package io.securecodebox.engine.execution;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import io.securecodebox.TestHelper;
import io.securecodebox.constants.DefaultFields;
+import io.securecodebox.engine.service.ExecutionTimeService;
import io.securecodebox.model.execution.ScanProcessExecution;
import io.securecodebox.model.execution.ScanProcessExecutionFactory;
import io.securecodebox.model.findings.OsiLayer;
@@ -36,12 +38,15 @@
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.Date;
+import java.util.Optional;
import java.util.UUID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
@@ -55,7 +60,7 @@
*/
public class DefaultScanProcessExecutionTest {
- private static final String DEFAULT_EXECUTION = "{\"id\":\"5a4e9d37-09b0-4109-badd-d79dfa8fce2a\",\"context\":\"TEST_CONTEXT\",\"automated\":false,\"scanners\":[{\"id\":\"62fa8ffb-e3bc-433e-b322-9c02108c5171\",\"type\":\"Test_SCANNER\",\"findings\":[{\"id\":\"49bf7fd3-8512-4d73-a28f-608e493cd726\",\"name\":\"BAD_TEST_FINDIG\",\"description\":\"Some coder has tested this!\",\"category\":\"COOL_TEST_STUFF\",\"osi_layer\":\"NOT_APPLICABLE\",\"severity\":\"HIGH\",\"reference\":{\"id\":\"UNI_CODE_STUFF\",\"source\":\"RISCOOL\"},\"hint\":\"You might wan't to blame Rüdiger!\",\"attributes\":{\"TEST\":\"Kekse\",\"HORRIBLE\":\"Coke\"},\"location\":\"mett.brot.securecodebox.io\",\"false_positive\":false}],\"rawFindings\":\"[{\\\"pudding\\\":\\\"Bier\\\"}]\"}]}";
+ private static final String DEFAULT_EXECUTION = "{\"id\":\"5a4e9d37-09b0-4109-badd-d79dfa8fce2a\",\"context\":\"TEST_CONTEXT\",\"automated\":false,\"scanners\":[{\"id\":\"62fa8ffb-e3bc-433e-b322-9c02108c5171\",\"type\":\"Test_SCANNER\",\"findings\":[{\"id\":\"49bf7fd3-8512-4d73-a28f-608e493cd726\",\"name\":\"BAD_TEST_FINDIG\",\"description\":\"Some coder has tested this!\",\"category\":\"COOL_TEST_STUFF\",\"osi_layer\":\"NOT_APPLICABLE\",\"severity\":\"HIGH\",\"reference\":{\"id\":\"UNI_CODE_STUFF\",\"source\":\"RISCOOL\"},\"hint\":\"You might wan't to blame Rüdiger!\",\"attributes\":{\"TEST\":\"Kekse\",\"HORRIBLE\":\"Coke\"},\"location\":\"mett.brot.securecodebox.io\",\"false_positive\":false}],\"rawFindings\":\"[{\\\"pudding\\\":\\\"Bier\\\"}]\"}],\"startDate\":504295320000,\"endDate\":504295620000,\"durationInMilliSeconds\":300000}";
public static final String SCANNER_SERIALIZE_RESULT = "{\"id\":\"62fa8ffb-e3bc-433e-b322-9c02108c5171\",\"type\":\"Test_SCANNER\",\"findings\":[{\"id\":\"49bf7fd3-8512-4d73-a28f-608e493cd726\",\"name\":\"BAD_TEST_FINDIG\",\"description\":\"Some coder has tested this!\",\"category\":\"COOL_TEST_STUFF\",\"osi_layer\":\"NOT_APPLICABLE\",\"severity\":\"HIGH\",\"reference\":{\"id\":\"UNI_CODE_STUFF\",\"source\":\"RISCOOL\"},\"hint\":\"You might wan't to blame Rüdiger!\",\"attributes\":{\"TEST\":\"Kekse\",\"HORRIBLE\":\"Coke\"},\"location\":\"mett.brot.securecodebox.io\",\"false_positive\":false}],\"rawFindings\":\"[{\\\"pudding\\\":\\\"Bier\\\"}]\"}";
String findingCache = "";
@@ -66,37 +71,51 @@ public class DefaultScanProcessExecutionTest {
@Mock
ScanProcessExecutionFactory processExecutionFactory;
@Mock
- DelegateExecution executionMock;
+ DelegateExecution execution;
+ @Mock
+ ExecutionTimeService executionTimeService;
DefaultScanProcessExecution underTest;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- underTest = new DefaultScanProcessExecution(executionMock);
+ underTest = new DefaultScanProcessExecution(execution);
+
+ objectMapper.registerModule(new Jdk8Module());
- when(processExecutionFactory.get(executionMock)).thenReturn(underTest);
- when(executionMock.hasVariable(eq(DefaultFields.PROCESS_FINDINGS.name()))).thenReturn(true);
- when(executionMock.getVariable(eq(DefaultFields.PROCESS_FINDINGS.name()))).thenAnswer((answer) -> findingCache);
+ when(executionTimeService.getStartDate()).thenReturn(
+ Date.from(LocalDateTime.of(1985, 12, 24, 18, 2).toInstant(ZoneOffset.UTC))
+ );
+ when(executionTimeService.getEndDate()).thenReturn(Optional.of(
+ Date.from(LocalDateTime.of(1985, 12, 24, 18, 7).toInstant(ZoneOffset.UTC))
+ ));
+ underTest.executionTimeService = executionTimeService;
+
+ when(processExecutionFactory.get(execution)).thenReturn(underTest);
+ when(execution.hasVariable(eq(DefaultFields.PROCESS_FINDINGS.name()))).thenReturn(true);
+ when(execution.getVariable(eq(DefaultFields.PROCESS_FINDINGS.name()))).thenAnswer((answer) -> findingCache);
doAnswer((Answer) invocation -> {
findingCache = (String) ((ObjectValueImpl)invocation.getArgument(1)).getValue();
return Void.TYPE;
- }).when(executionMock).setVariable(eq(DefaultFields.PROCESS_FINDINGS.name()), any());
+ }).when(execution).setVariable(eq(DefaultFields.PROCESS_FINDINGS.name()), any());
- when(executionMock.hasVariable(eq(DefaultFields.PROCESS_TARGETS.name()))).thenReturn(true);
- when(executionMock.getVariable(eq(DefaultFields.PROCESS_TARGETS.name()))).thenAnswer((answer) -> targetCache);
+ when(execution.hasVariable(eq(DefaultFields.PROCESS_TARGETS.name()))).thenReturn(true);
+ when(execution.getVariable(eq(DefaultFields.PROCESS_TARGETS.name()))).thenAnswer((answer) -> targetCache);
doAnswer((Answer) invocation -> {
targetCache = (String) ((ObjectValueImpl)invocation.getArgument(1)).getValue();
return Void.TYPE;
- }).when(executionMock).setVariable(eq(DefaultFields.PROCESS_TARGETS.name()), any());
+ }).when(execution).setVariable(eq(DefaultFields.PROCESS_TARGETS.name()), any());
}
@Test
public void testSerialize() throws Exception {
DelegateExecution process = mockDelegateExcecution();
- ScanProcessExecution execution = new DefaultScanProcessExecution(process);
- String s = objectMapper.writeValueAsString(execution);
+ DefaultScanProcessExecution execution = new DefaultScanProcessExecution(process);
+
+ execution.executionTimeService = executionTimeService;
+ String s = objectMapper.writeValueAsString((ScanProcessExecution) execution);
System.out.println(s);
assertEquals(DEFAULT_EXECUTION, s);
@@ -126,9 +145,9 @@ public void testAppendAndClearFindings() throws Exception {
underTest.appendFinding(TestHelper.createBasicFinding(finding1Id));
underTest.appendFinding(TestHelper.createBasicFindingDifferent(finding2Id));
- Mockito.verify(executionMock, times(2)).setVariable(eq(DefaultFields.PROCESS_FINDINGS.name()), any());
+ Mockito.verify(execution, times(2)).setVariable(eq(DefaultFields.PROCESS_FINDINGS.name()), any());
- ScanProcessExecution processExecution = processExecutionFactory.get(executionMock);
+ ScanProcessExecution processExecution = processExecutionFactory.get(execution);
assertEquals(2, processExecution.getFindings().size());
@@ -163,9 +182,9 @@ public void testAppendAndClearFindings() throws Exception {
//
underTest.clearFindings();
- Mockito.verify(executionMock, atLeastOnce()).getVariable(eq(DefaultFields.PROCESS_FINDINGS.name()));
- Mockito.verify(executionMock, times(3)).setVariable(eq(DefaultFields.PROCESS_FINDINGS.name()), any());
- Mockito.verifyNoMoreInteractions(executionMock);
+ Mockito.verify(execution, atLeastOnce()).getVariable(eq(DefaultFields.PROCESS_FINDINGS.name()));
+ Mockito.verify(execution, times(3)).setVariable(eq(DefaultFields.PROCESS_FINDINGS.name()), any());
+ Mockito.verifyNoMoreInteractions(execution);
assertEquals(0, processExecution.getFindings().size());
}
@@ -177,9 +196,9 @@ public void testAppendAndClearTargets() throws Exception {
underTest.appendTarget(TestHelper.createBaiscTarget());
underTest.appendTarget(TestHelper.createTarget("http://w1.w2.www", "some wired"));
- Mockito.verify(executionMock, times(2)).setVariable(eq(DefaultFields.PROCESS_TARGETS.name()), any());
+ Mockito.verify(execution, times(2)).setVariable(eq(DefaultFields.PROCESS_TARGETS.name()), any());
- ScanProcessExecution processExecution = processExecutionFactory.get(executionMock);
+ ScanProcessExecution processExecution = processExecutionFactory.get(execution);
assertEquals(2, processExecution.getTargets().size());
@@ -201,9 +220,9 @@ public void testAppendAndClearTargets() throws Exception {
// Clear targets
//
underTest.clearTargets();
- Mockito.verify(executionMock, atLeastOnce()).getVariable(eq(DefaultFields.PROCESS_TARGETS.name()));
- Mockito.verify(executionMock, times(3)).setVariable(eq(DefaultFields.PROCESS_TARGETS.name()), any());
- Mockito.verifyNoMoreInteractions(executionMock);
+ Mockito.verify(execution, atLeastOnce()).getVariable(eq(DefaultFields.PROCESS_TARGETS.name()));
+ Mockito.verify(execution, times(3)).setVariable(eq(DefaultFields.PROCESS_TARGETS.name()), any());
+ Mockito.verifyNoMoreInteractions(execution);
assertEquals(0, processExecution.getTargets().size());
}
diff --git a/scb-persistenceproviders/elasticsearch-persistenceprovider/pom.xml b/scb-persistenceproviders/elasticsearch-persistenceprovider/pom.xml
index f02b6182..ae7c9a4d 100644
--- a/scb-persistenceproviders/elasticsearch-persistenceprovider/pom.xml
+++ b/scb-persistenceproviders/elasticsearch-persistenceprovider/pom.xml
@@ -71,6 +71,10 @@
1.2.1
test
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jdk8
+
diff --git a/scb-persistenceproviders/elasticsearch-persistenceprovider/src/main/java/io/securecodebox/persistence/elasticsearch/ElasticSearchPersistenceProvider.java b/scb-persistenceproviders/elasticsearch-persistenceprovider/src/main/java/io/securecodebox/persistence/elasticsearch/ElasticSearchPersistenceProvider.java
index f0d9eab2..3b8a000f 100644
--- a/scb-persistenceproviders/elasticsearch-persistenceprovider/src/main/java/io/securecodebox/persistence/elasticsearch/ElasticSearchPersistenceProvider.java
+++ b/scb-persistenceproviders/elasticsearch-persistenceprovider/src/main/java/io/securecodebox/persistence/elasticsearch/ElasticSearchPersistenceProvider.java
@@ -22,6 +22,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import io.securecodebox.model.findings.Finding;
import io.securecodebox.model.securitytest.SecurityTest;
import io.securecodebox.persistence.PersistenceException;
@@ -168,6 +169,7 @@ public void persist(SecurityTest securityTest) throws PersistenceException{
}
ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.registerModule(new Jdk8Module());
try {
checkForSecurityTestIdExistence(securityTest);
@@ -336,6 +338,7 @@ private String readFileResource(String file) {
private Map serializeAndRemove(Object object, String... toRemove) {
ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.registerModule(new Jdk8Module());
try {
String jsonString = objectMapper.writeValueAsString(object);
Map result = objectMapper.readValue(jsonString, new TypeReference