Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[backend] catch error when execution fails for some asset (#1863) #1864

Merged
merged 4 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@
Inject inject = executableInject.getInjection().getInject();

// We are now checking if we depend on another inject and if it did not failed
Optional<List<String>> errorMessages = null;
Optional<List<String>> errorMessages = Optional.empty();

Check warning on line 184 in openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java#L184

Added line #L184 was not covered by tests
if (executableInject.getExercise() != null) {
errorMessages = getErrorMessagesPreExecution(executableInject.getExercise().getId(), inject);
}
Expand Down Expand Up @@ -231,24 +231,19 @@
ExecutableInject newExecutableInject = executableInject;
if (Boolean.TRUE.equals(injectorContract.getNeedsExecutor())) {
// Status
InjectStatus statusSaved =
initializeInjectStatus(inject, ExecutionStatus.EXECUTING, null);
initializeInjectStatus(inject, ExecutionStatus.EXECUTING, null);

Check warning on line 234 in openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java#L234

Added line #L234 was not covered by tests
try {
newExecutableInject =
this.executionExecutorService.launchExecutorContext(executableInject, inject);
} catch (Exception e) {
ExecutionTraceStatus traceStatus =
e.getMessage().startsWith("Asset error")
? ExecutionTraceStatus.ASSET_INACTIVE
: ExecutionTraceStatus.ERROR;

statusSaved
.getTraces()
.add(InjectStatusExecution.traceError(traceStatus, e.getMessage()));

statusSaved.setName(ExecutionStatus.ERROR);
injectStatusRepository.save(statusSaved);
throw new RuntimeException(e);
} catch (Exception e) {
InjectStatus injectStatus =

Check warning on line 240 in openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java#L239-L240

Added lines #L239 - L240 were not covered by tests
inject
.getStatus()
.orElseThrow(() -> new IllegalArgumentException("Status should exists"));
injectStatus.setName(ExecutionStatus.ERROR);
injectStatusRepository.save(injectStatus);
return;

Check warning on line 246 in openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java#L242-L246

Added lines #L242 - L246 were not covered by tests
}
}
if (externalInjector.isExternal()) {
Expand All @@ -264,7 +259,7 @@
InjectStatusExecution.traceError("Inject does not have a contract")));
}

private InjectStatus initializeInjectStatus(
private void initializeInjectStatus(
Inject inject, ExecutionStatus status, @Nullable InjectStatusExecution trace) {
InjectStatus injectStatus =
inject
Expand All @@ -282,7 +277,8 @@
injectStatus.setName(status);
injectStatus.setTrackingSentDate(Instant.now());
injectStatus.setCommandsLines(injectUtils.getCommandsLinesFromInject(inject));
return injectStatusRepository.save(injectStatus);
injectStatusRepository.save(injectStatus);
inject.setStatus(injectStatus);

Check warning on line 281 in openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java#L280-L281

Added lines #L280 - L281 were not covered by tests
}

/**
Expand Down Expand Up @@ -353,7 +349,9 @@

injectDependencies.forEach(
injectDependency -> {
injectDependency.getInjectDependencyCondition().getConditions().stream()
injectDependency
.getInjectDependencyCondition()
.getConditions()

Check warning on line 354 in openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/scheduler/jobs/InjectsExecutionJob.java#L352-L354

Added lines #L352 - L354 were not covered by tests
.forEach(
condition -> {
mapCondition.put(condition.getKey(), false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.openbas.execution;

public class ExecutionExecutorException extends RuntimeException {
public ExecutionExecutorException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -1,70 +1,33 @@
package io.openbas.execution;

import io.openbas.asset.AssetGroupService;
import io.openbas.database.model.Asset;
import io.openbas.database.model.*;
import io.openbas.database.model.Executor;
import io.openbas.database.model.Inject;
import io.openbas.database.repository.InjectStatusRepository;
import io.openbas.executors.caldera.config.CalderaExecutorConfig;
import io.openbas.executors.caldera.service.CalderaExecutorContextService;
import io.openbas.executors.openbas.service.OpenBASExecutorContextService;
import io.openbas.executors.tanium.config.TaniumExecutorConfig;
import io.openbas.executors.tanium.service.TaniumExecutorContextService;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
@Log
public class ExecutionExecutorService {
private AssetGroupService assetGroupService;

private CalderaExecutorConfig calderaExecutorConfig;

private CalderaExecutorContextService calderaExecutorContextService;

private TaniumExecutorConfig taniumExecutorConfig;

private TaniumExecutorContextService taniumExecutorContextService;

private OpenBASExecutorContextService openBASExecutorContextService;

@Autowired
public void setOpenBASExecutorContextService(
OpenBASExecutorContextService openBASExecutorContextService) {
this.openBASExecutorContextService = openBASExecutorContextService;
}

@Autowired
public void setAssetGroupService(AssetGroupService assetGroupService) {
this.assetGroupService = assetGroupService;
}

@Autowired
public void setCalderaExecutorConfig(CalderaExecutorConfig calderaExecutorConfig) {
this.calderaExecutorConfig = calderaExecutorConfig;
}

@Autowired
public void setCalderaExecutorContextService(
CalderaExecutorContextService calderaExecutorContextService) {
this.calderaExecutorContextService = calderaExecutorContextService;
}

@Autowired
public void setTaniumExecutorConfig(TaniumExecutorConfig taniumExecutorConfig) {
this.taniumExecutorConfig = taniumExecutorConfig;
}

@Autowired
public void setTaniumExecutorContextService(
TaniumExecutorContextService taniumExecutorContextService) {
this.taniumExecutorContextService = taniumExecutorContextService;
}
private final AssetGroupService assetGroupService;
private final CalderaExecutorConfig calderaExecutorConfig;
private final CalderaExecutorContextService calderaExecutorContextService;
private final TaniumExecutorConfig taniumExecutorConfig;
private final TaniumExecutorContextService taniumExecutorContextService;
private final OpenBASExecutorContextService openBASExecutorContextService;
private final InjectStatusRepository injectStatusRepository;

public ExecutableInject launchExecutorContext(ExecutableInject executableInject, Inject inject)
throws InterruptedException {
Expand All @@ -79,10 +42,32 @@ public ExecutableInject launchExecutorContext(ExecutableInject executableInject,
.assetsFromAssetGroup(assetGroup.getId())
.stream()))
.toList();
InjectStatus injectStatus =
inject.getStatus().orElseThrow(() -> new IllegalArgumentException("Status should exists"));
AtomicBoolean atLeastOneExecution = new AtomicBoolean(false);
assets.forEach(
asset -> {
launchExecutorContextForAsset(inject, asset);
try {
launchExecutorContextForAsset(inject, asset);
atLeastOneExecution.set(true);
} catch (RuntimeException e) {
ExecutionTraceStatus traceStatus =
e.getMessage().startsWith("Asset error")
? ExecutionTraceStatus.ASSET_INACTIVE
: ExecutionTraceStatus.ERROR;

injectStatus
.getTraces()
.add(InjectStatusExecution.traceError(traceStatus, e.getMessage()));
this.injectStatusRepository.save(injectStatus);
}
});
// if launchExecutorContextForAsset fail for every assets we throw to manually set injectStatus
// to error
if (!atLeastOneExecution.get()) {
throw new ExecutionExecutorException("No asset executed");
}

return executableInject;
}

Expand All @@ -106,12 +91,10 @@ private void launchExecutorContextForAsset(Inject inject, Asset asset) {
}
this.taniumExecutorContextService.launchExecutorSubprocess(inject, asset);
}
case "openbas_agent" -> {
this.openBASExecutorContextService.launchExecutorSubprocess(inject, asset);
}
default -> {
throw new RuntimeException("Fatal error: Unsupported executor " + executor.getType());
}
case "openbas_agent" ->
this.openBASExecutorContextService.launchExecutorSubprocess(inject, asset);
default ->
throw new RuntimeException("Fatal error: Unsupported executor " + executor.getType());
}
}
}
Expand Down