From b28ad1842c528eb4b2c128e70e105d4fe1dc7e9e Mon Sep 17 00:00:00 2001 From: Samuel Hassine Date: Fri, 31 May 2024 02:56:17 +0200 Subject: [PATCH] [backend] Enhance Caldera traces --- .../injectors/caldera/CalderaExecutor.java | 2 +- .../CalderaResultCollectorService.java | 99 +++++++++++-------- 2 files changed, 58 insertions(+), 43 deletions(-) diff --git a/openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java b/openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java index 65be9c2c9c..0d15c018be 100644 --- a/openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java +++ b/openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java @@ -80,7 +80,7 @@ public ExecutionProcess process(@NotNull final Execution execution, @NotNull fin InjectExpectationSignature.builder().type(EXPECTATION_SIGNATURE_TYPE_COMMAND_LINE).value(exploitResult.getCommand()).build() ); computeExpectationsForAsset(expectations, content, executionEndpoint.getParent(), isInGroup, injectExpectationSignatures); - execution.addTrace(traceInfo("Caldera executed the ability on asset " + asset.getName() + " using " + executionEndpoint.getProcessName() + " (linkID: " + exploitResult.getLinkId() + ")")); + execution.addTrace(traceInfo("Caldera executed the ability on asset " + asset.getName() + " using " + executionEndpoint.getProcessName() + " (paw: " + executionEndpoint.getExternalReference() + ", linkID: " + exploitResult.getLinkId() + ")")); } else { execution.addTrace(traceError("Caldera failed to execute the ability on asset " + asset.getName() + " (" + result + ")")); } diff --git a/openbas-api/src/main/java/io/openbas/injectors/caldera/service/CalderaResultCollectorService.java b/openbas-api/src/main/java/io/openbas/injectors/caldera/service/CalderaResultCollectorService.java index 53643a7926..137251d88a 100644 --- a/openbas-api/src/main/java/io/openbas/injectors/caldera/service/CalderaResultCollectorService.java +++ b/openbas-api/src/main/java/io/openbas/injectors/caldera/service/CalderaResultCollectorService.java @@ -59,69 +59,85 @@ public void run() { List injectStatuses = this.injectStatusRepository.pendingForInjectType(CalderaContract.TYPE); // For each one ask for traces and status injectStatuses.forEach((injectStatus -> { - log.log(Level.INFO, "Found inject status: " + injectStatus); + log.log(Level.INFO, "Found inject status: " + injectStatus.getId()); // Add traces and close inject if needed. Instant finalExecutionTime = injectStatus.getTrackingSentDate(); List linkIds = injectStatus.statusIdentifiers(); - log.log(Level.INFO, "Found links IDs: " + linkIds); - List completedActions = new ArrayList<>(); - for (String linkId : linkIds) { - ResultStatus resultStatus = new ResultStatus(); - try { - log.log(Level.INFO, "Trying to get result for " + linkId); - resultStatus = this.calderaService.results(linkId); - } catch (Exception e) { - injectStatus.getTraces().add(traceError("Cannot get result for linkID " + linkId + ", injection has failed")); - resultStatus.setFail(true); - completedActions.add(resultStatus); - injectStatus.setTrackingTotalError(injectStatus.getTrackingTotalError() + 1); - } - if (resultStatus.getPaw() == null) { - if (injectStatus.getTrackingSentDate().isBefore(Instant.now().minus(EXPIRATION_TIME / 60, ChronoUnit.MINUTES))) { + if (linkIds.isEmpty()) { + computeInjectStatus(injectStatus, finalExecutionTime, 0, 0); + computeInject(injectStatus); + } else { + log.log(Level.INFO, "Found links IDs: " + linkIds); + List completedActions = new ArrayList<>(); + for (String linkId : linkIds) { + ResultStatus resultStatus = new ResultStatus(); + try { + log.log(Level.INFO, "Trying to get result for " + linkId); + resultStatus = this.calderaService.results(linkId); + } catch (Exception e) { injectStatus.getTraces().add(traceError("Cannot get result for linkID " + linkId + ", injection has failed")); + log.log(Level.INFO, "Cannot get result for linkID " + linkId + ", injection has failed"); resultStatus.setFail(true); completedActions.add(resultStatus); injectStatus.setTrackingTotalError(injectStatus.getTrackingTotalError() + 1); } - } else { - if (resultStatus.isComplete()) { - completedActions.add(resultStatus); - injectStatus.setTrackingTotalSuccess(injectStatus.getTrackingTotalSuccess() + 1); - // Compute biggest execution time - if (resultStatus.getFinish().isAfter(finalExecutionTime)) { - finalExecutionTime = resultStatus.getFinish(); + if (resultStatus.getPaw() == null) { + if (injectStatus.getTrackingSentDate().isBefore(Instant.now().minus(EXPIRATION_TIME / 60, ChronoUnit.MINUTES))) { + injectStatus.getTraces().add(traceError("Cannot get result for linkID " + linkId + ", injection has failed")); + log.log(Level.INFO, "Cannot get result for linkID " + linkId + ", injection has failed"); + resultStatus.setFail(true); + completedActions.add(resultStatus); + injectStatus.setTrackingTotalError(injectStatus.getTrackingTotalError() + 1); + } + } else { + if (resultStatus.isComplete()) { + completedActions.add(resultStatus); + if (resultStatus.isFail()) { + injectStatus.setTrackingTotalError(injectStatus.getTrackingTotalError() + 1); + injectStatus.getTraces().add(traceError("Failed result for linkID " + linkId + " (" + resultStatus.getContent() + ")")); + } else { + injectStatus.setTrackingTotalSuccess(injectStatus.getTrackingTotalSuccess() + 1); + injectStatus.getTraces().add(traceInfo("Success result for linkID " + linkId + " (" + resultStatus.getContent() + ")")); + } + // Compute biggest execution time + if (resultStatus.getFinish().isAfter(finalExecutionTime)) { + finalExecutionTime = resultStatus.getFinish(); + } + } else if (injectStatus.getTrackingSentDate().isBefore(Instant.now().minus(5L, ChronoUnit.MINUTES))) { + injectStatus.getTraces().add(traceError("Timeout on linkID " + linkId + ", injection has failed")); + log.log(Level.INFO, "Timeout on linkID " + linkId + ", injection has failed"); + resultStatus.setFail(true); + completedActions.add(resultStatus); + injectStatus.setTrackingTotalError(injectStatus.getTrackingTotalError() + 1); } - } else if (injectStatus.getTrackingSentDate().isBefore(Instant.now().minus(5L, ChronoUnit.MINUTES))) { - injectStatus.getTraces().add(traceError("Timeout on linkID " + linkId + ", injection has failed")); - resultStatus.setFail(true); - completedActions.add(resultStatus); - injectStatus.setTrackingTotalError(injectStatus.getTrackingTotalError() + 1); } } - } - // Compute status only if all actions are completed - if (!linkIds.isEmpty() && completedActions.size() == linkIds.size()) { - int failedActions = (int) completedActions.stream().filter(ResultStatus::isFail).count(); - computeInjectStatus(injectStatus, finalExecutionTime, completedActions.size(), failedActions); - // Update related inject - computeInject(injectStatus); + // Compute status only if all actions are completed + if (completedActions.size() == linkIds.size()) { + int failedActions = (int) completedActions.stream().filter(ResultStatus::isFail).count(); + computeInjectStatus(injectStatus, finalExecutionTime, completedActions.size(), failedActions); + // Update related inject + computeInject(injectStatus); + } } })); } // -- INJECT STATUS -- - @Transactional public void computeInjectStatus( @NotNull final InjectStatus injectStatus, @NotNull final Instant finalExecutionTime, final int completedActions, final int failedActions) { - boolean hasError = injectStatus.getTraces().stream().anyMatch(trace -> trace.getStatus().equals(ExecutionStatus.ERROR)); - injectStatus.setName(hasError ? ExecutionStatus.ERROR : ExecutionStatus.SUCCESS); - injectStatus.getTraces().add( - traceInfo("caldera", "Caldera executed the ability on " + (completedActions - failedActions) + "/" + completedActions + " asset(s)") - ); + if (injectStatus.getTraces().stream().filter(injectStatusExecution -> injectStatusExecution.getStatus().equals(ExecutionStatus.ERROR)).count() == completedActions) { + injectStatus.setName(ExecutionStatus.ERROR); + } else if (injectStatus.getTraces().stream().anyMatch(trace -> trace.getStatus().equals(ExecutionStatus.ERROR))) { + injectStatus.setName(ExecutionStatus.PARTIAL); + } else { + injectStatus.setName(ExecutionStatus.SUCCESS); + } + injectStatus.getTraces().add(traceInfo("caldera", "Caldera executed the ability on " + (completedActions - failedActions) + "/" + completedActions + " asset(s)")); long executionTime = (finalExecutionTime.toEpochMilli() - injectStatus.getTrackingSentDate().toEpochMilli()); injectStatus.setTrackingTotalExecutionTime(executionTime); injectStatus.setTrackingEndDate(Instant.now()); @@ -130,7 +146,6 @@ public void computeInjectStatus( // -- INJECT -- - @Transactional public void computeInject(@NotNull final InjectStatus injectStatus) { Inject relatedInject = injectStatus.getInject(); relatedInject.setUpdatedAt(Instant.now());