diff --git a/openbas-api/src/test/java/io/openbas/rest/InjectApiTest.java b/openbas-api/src/test/java/io/openbas/rest/InjectApiTest.java index 96da970f1b..7896f79a17 100644 --- a/openbas-api/src/test/java/io/openbas/rest/InjectApiTest.java +++ b/openbas-api/src/test/java/io/openbas/rest/InjectApiTest.java @@ -1,37 +1,59 @@ package io.openbas.rest; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.jayway.jsonpath.JsonPath; import io.openbas.IntegrationTest; import io.openbas.database.model.InjectorContract; import io.openbas.database.model.*; import io.openbas.database.repository.*; import io.openbas.rest.exercise.service.ExerciseService; +import io.openbas.rest.inject.form.DirectInjectInput; import io.openbas.rest.inject.form.InjectInput; import io.openbas.service.ScenarioService; import io.openbas.utils.fixtures.InjectExpectationFixture; import io.openbas.utils.mockUser.WithMockObserverUser; import io.openbas.utils.mockUser.WithMockPlannerUser; +import jakarta.annotation.Resource; +import jakarta.mail.internet.MimeMessage; +import jakarta.servlet.ServletException; import org.junit.jupiter.api.*; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentMatchers; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.util.ResourceUtils; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; import java.time.Instant; import java.util.List; +import static io.openbas.config.SessionHelper.currentUser; import static io.openbas.database.model.ExerciseStatus.RUNNING; import static io.openbas.injectors.email.EmailContract.EMAIL_DEFAULT; import static io.openbas.rest.exercise.ExerciseApi.EXERCISE_URI; import static io.openbas.rest.inject.InjectApi.INJECT_URI; import static io.openbas.rest.scenario.ScenarioApi.SCENARIO_URI; import static io.openbas.utils.JsonUtils.asJsonString; +import static io.openbas.utils.fixtures.InjectFixture.getInjectForEmailContract; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestInstance(PER_CLASS) +@ExtendWith(MockitoExtension.class) class InjectApiTest extends IntegrationTest { static Exercise EXERCISE; @@ -63,6 +85,12 @@ class InjectApiTest extends IntegrationTest { private TeamRepository teamRepository; @Autowired private InjectorContractRepository injectorContractRepository; + @Autowired + private UserRepository userRepository; + @Resource + private ObjectMapper objectMapper; + @MockBean + private JavaMailSender javaMailSender; @BeforeAll void beforeAll() { @@ -327,6 +355,128 @@ void updateInjectForSimulationTest() throws Exception { assertEquals(injectTitle, JsonPath.read(response, "$.inject_title")); } + @DisplayName("Execute an email inject for exercise") + @Test + @WithMockPlannerUser + void executeEmailInjectForExerciseTest() throws Exception { + // -- PREPARE -- + InjectorContract injectorContract = this.injectorContractRepository.findById(EMAIL_DEFAULT).orElseThrow(); + Inject inject = getInjectForEmailContract(injectorContract); + User user = userRepository.findById(currentUser().getId()).orElseThrow(); + DirectInjectInput input = new DirectInjectInput(); + input.setTitle(inject.getTitle()); + input.setDescription(inject.getDescription()); + input.setInjectorContract(inject.getInjectorContract().orElseThrow().getId()); + input.setUserIds(List.of(user.getId())); + ObjectNode content = objectMapper.createObjectNode(); + content.set("subject", objectMapper.convertValue("Subject", JsonNode.class)); + content.set("body", objectMapper.convertValue("Test body", JsonNode.class)); + content.set("expectationType", objectMapper.convertValue("none", JsonNode.class)); + input.setContent(content); + + MockMultipartFile inputJson = new MockMultipartFile("input", null, "application/json", + objectMapper.writeValueAsString(input).getBytes()); + + // Getting a test file + File testFile = ResourceUtils.getFile("classpath:xls-test-files/test_file_1.xlsx"); + InputStream in = new FileInputStream(testFile); + MockMultipartFile fileJson = new MockMultipartFile("file", + "my-awesome-file.xls", + "application/xlsx", + in.readAllBytes()); + + // Mock the behavior of JavaMailSender + doNothing().when(javaMailSender).send(ArgumentMatchers.any(SimpleMailMessage.class)); + MimeMessage mimeMessage = mock(MimeMessage.class); + when(javaMailSender.createMimeMessage()).thenReturn(mimeMessage); + + // -- EXECUTE -- + String response = mvc.perform(multipart(EXERCISE_URI + "/" + EXERCISE.getId() + "/inject") + .file(inputJson) + .file(fileJson)) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse() + .getContentAsString(); + + // -- ASSERT -- + assertNotNull(response); + assertEquals("SUCCESS", JsonPath.read(response, "$.status_name")); + + //-- THEN --- + userRepository.delete(user); + + } + + @DisplayName("Execute an email inject for exercise with no team") + @Test + @WithMockPlannerUser + void executeEmailInjectForExerciseWithNoTeam() throws Exception { + // -- PREPARE -- + InjectorContract injectorContract = this.injectorContractRepository.findById(EMAIL_DEFAULT).orElseThrow(); + Inject inject = getInjectForEmailContract(injectorContract); + User user = userRepository.findById(currentUser().getId()).orElseThrow(); + DirectInjectInput input = new DirectInjectInput(); + input.setTitle(inject.getTitle()); + input.setDescription(inject.getDescription()); + input.setInjectorContract(inject.getInjectorContract().orElseThrow().getId()); + ObjectNode content = objectMapper.createObjectNode(); + content.set("subject", objectMapper.convertValue("Subject", JsonNode.class)); + content.set("body", objectMapper.convertValue("Test body", JsonNode.class)); + content.set("expectationType", objectMapper.convertValue("none", JsonNode.class)); + input.setContent(content); + + MockMultipartFile inputJson = new MockMultipartFile("input", null, "application/json", + objectMapper.writeValueAsString(input).getBytes()); + + // -- EXECUTE -- + String response = mvc.perform(multipart(EXERCISE_URI + "/" + EXERCISE.getId() + "/inject") + .file(inputJson)) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse() + .getContentAsString(); + + // -- ASSERT -- + assertNotNull(response); + assertEquals("ERROR", JsonPath.read(response, "$.status_name")); + assertEquals("Email needs at least one user", JsonPath.read(response, "$.status_traces[0].execution_message")); + + //-- THEN --- + userRepository.delete(user); + } + + @DisplayName("Execute an email inject for exercise with no content") + @Test + @WithMockPlannerUser + void executeEmailInjectForExerciseWithNoContentTest() throws Exception { + // -- PREPARE -- + InjectorContract injectorContract = this.injectorContractRepository.findById(EMAIL_DEFAULT).orElseThrow(); + Inject inject = getInjectForEmailContract(injectorContract); + User user = userRepository.findById(currentUser().getId()).orElseThrow(); + DirectInjectInput input = new DirectInjectInput(); + input.setTitle(inject.getTitle()); + input.setDescription(inject.getDescription()); + input.setInjectorContract(inject.getInjectorContract().orElseThrow().getId()); + input.setUserIds(List.of(user.getId())); + + MockMultipartFile inputJson = new MockMultipartFile("input", null, "application/json", + objectMapper.writeValueAsString(input).getBytes()); + + //-- ASSERT + Exception exception = assertThrows(ServletException.class, + () -> mvc.perform(multipart(EXERCISE_URI + "/" + EXERCISE.getId() + "/inject") + .file(inputJson))); + + String expectedMessage = "Inject is empty"; + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(expectedMessage)); + + //-- THEN --- + userRepository.delete(user); + } + // -- BULK DELETE -- @DisplayName("Delete list of inject for exercise") diff --git a/openbas-api/src/test/java/io/openbas/utils/fixtures/ExerciseFixture.java b/openbas-api/src/test/java/io/openbas/utils/fixtures/ExerciseFixture.java index 309d0ddfc8..651d4bb2e7 100644 --- a/openbas-api/src/test/java/io/openbas/utils/fixtures/ExerciseFixture.java +++ b/openbas-api/src/test/java/io/openbas/utils/fixtures/ExerciseFixture.java @@ -9,41 +9,49 @@ public class ExerciseFixture { - public static final String EXERCISE_NAME = "Exercise test"; + public static final String EXERCISE_NAME = "Exercise test"; - public static Exercise getExercise() { - return getExercise(null); - } - - public static Exercise getExercise(List exerciseTeams) { - Exercise exercise = new Exercise(); - exercise.setName(EXERCISE_NAME); - if(exerciseTeams != null){ - exercise.setTeams(exerciseTeams); - } - return exercise; - } - - public static Exercise createDefaultCrisisExercise() { - Exercise exercise = new Exercise(); - exercise.setName("Crisis exercise"); - exercise.setDescription("A crisis exercise for my enterprise"); - exercise.setSubtitle("A crisis exercise"); - exercise.setFrom("exercise@mail.fr"); - exercise.setCategory("crisis-communication"); - return exercise; - } + public static Exercise getExercise() { + return getExercise(null); + } - public static Exercise createDefaultIncidentResponseExercise() { - Exercise exercise = new Exercise(); - exercise.setName("Incident response exercise"); - exercise.setDescription("An incident response exercise for my enterprise"); - exercise.setSubtitle("An incident response exercise"); - exercise.setFrom("exercise@mail.fr"); - exercise.setCategory("incident-response"); - exercise.setStatus(ExerciseStatus.SCHEDULED); - exercise.setStart(Instant.now()); - return exercise; + public static Exercise getExercise(List exerciseTeams) { + Exercise exercise = new Exercise(); + exercise.setName(EXERCISE_NAME); + if (exerciseTeams != null) { + exercise.setTeams(exerciseTeams); } + return exercise; + } + + public static Exercise createDefaultCrisisExercise() { + Exercise exercise = new Exercise(); + exercise.setName("Crisis exercise"); + exercise.setDescription("A crisis exercise for my enterprise"); + exercise.setSubtitle("A crisis exercise"); + exercise.setFrom("exercise@mail.fr"); + exercise.setCategory("crisis-communication"); + return exercise; + } + + public static Exercise createDefaultIncidentResponseExercise() { + Exercise exercise = new Exercise(); + exercise.setName("Incident response exercise"); + exercise.setDescription("An incident response exercise for my enterprise"); + exercise.setSubtitle("An incident response exercise"); + exercise.setFrom("exercise@mail.fr"); + exercise.setCategory("incident-response"); + exercise.setStatus(ExerciseStatus.SCHEDULED); + exercise.setStart(Instant.now()); + return exercise; + } + + /* + _ create exercise with team containing a user with email (user enabled) + _ create exercise with team containing a user with email (user not enabled) + _ create exercise without team + _ create exercise with team without user + _ create email + */ } diff --git a/openbas-api/src/test/java/io/openbas/utils/fixtures/InjectFixture.java b/openbas-api/src/test/java/io/openbas/utils/fixtures/InjectFixture.java index 42d700b1a1..83672d66b6 100644 --- a/openbas-api/src/test/java/io/openbas/utils/fixtures/InjectFixture.java +++ b/openbas-api/src/test/java/io/openbas/utils/fixtures/InjectFixture.java @@ -3,18 +3,17 @@ import io.openbas.database.model.Inject; import io.openbas.database.model.InjectorContract; -import static io.openbas.injectors.email.EmailContract.TYPE; - public class InjectFixture { - public static final String INJECT_EMAIL_NAME = "Test email inject"; + public static final String INJECT_EMAIL_NAME = "Test email inject"; + + public static Inject getInjectForEmailContract(InjectorContract injectorContract) { + Inject inject = new Inject(); + inject.setTitle(INJECT_EMAIL_NAME); + inject.setInjectorContract(injectorContract); + inject.setEnabled(true); + inject.setDependsDuration(0L); + return inject; + } - public static Inject getInjectForEmailContract(InjectorContract injectorContract) { - Inject inject = new Inject(); - inject.setTitle(INJECT_EMAIL_NAME); - inject.setInjectorContract(injectorContract); - inject.setEnabled(true); - inject.setDependsDuration(0L); - return inject; - } } diff --git a/openbas-api/src/test/resources/application.properties b/openbas-api/src/test/resources/application.properties index e7d127e550..ed8360db68 100644 --- a/openbas-api/src/test/resources/application.properties +++ b/openbas-api/src/test/resources/application.properties @@ -3,21 +3,17 @@ info.app.name=OpenBAS # suppress inspection "SpringBootApplicationProperties" info.app.version=Testing - # OpenBAS configuration openbas.base-url=http://localhost:8080 openbas.admin.email=admin@openbas.io openbas.admin.password=admin openbas.admin.token=0d17ce9a-f3a8-4c6d-9721-c98dc3dc023f - # Server configuration server.servlet.context-path=/ - # rabbit mq openbas.rabbitmq.management-insecure=true openbas.rabbitmq.trust-store-password= openbas.rabbitmq.trust.store= - # Authenticators ## Local openbas.auth-local-enable=false @@ -25,33 +21,29 @@ openbas.auth-local-enable=false openbas.auth-openid-enable=false ## Kerberos openbas.auth-kerberos-enable=false - spring.datasource.url=jdbc:postgresql://localhost:5433/openbas spring.datasource.username=openbas spring.datasource.password=openbas - # Minio Properties minio.endpoint=localhost minio.port=10000 minio.bucket=openbas minio.access-key=minioadmin minio.access-secret=minioadmin - ############# # INJECTORS # ############# - # Mail config (Always available) -openbas.default-mailer=no-reply@openbas.io openbas.default-reply-to=contact@openbas.io -spring.mail.host=smtp.gmail.com -spring.mail.port=587 +openbas.default-mailer=no-reply@openbas.io +spring.mail.host=ssl0.ovh.net +spring.mail.port=465 spring.mail.username= spring.mail.password= spring.mail.properties.mail.smtp.ssl.trust=* spring.mail.properties.mail.smtp.ssl.enable=true spring.mail.properties.mail.smtp.auth=true -spring.mail.properties.mail.smtp.starttls.enable=true +spring.mail.properties.mail.smtp.starttls.enable=false # IMAP Configuration openbas.mail.imap.enabled=false openbas.mail.imap.host=imap.mail.com @@ -65,37 +57,26 @@ openbas.mail.imap.ssl.trust=* openbas.mail.imap.ssl.enable=true openbas.mail.imap.auth=true openbas.mail.imap.starttls.enable=true - # OVH SMS config ovh.sms.enable=false - # Mastodon config mastodon.enable=false - # Airbus LADE config lade.enable=false - # Injector Http config http.enable=false - # Injector Caldera config injector.caldera.enable=false - # XLS Import openbas.xls.import.mail.enable=true openbas.xls.import.sms.enable=true - ############# # COLLECTORS # ############# - # Collectors - ## Collector user collector.users.enable=false - ## Collector MITRE ATT&CK collector.mitre-attack.enable=false - ## Collector Caldera collector.caldera.enable=false