From 0bdc1d05825a6c804bf964eea95e3bfd9e22e340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Mon, 16 Feb 2026 09:58:44 +0100 Subject: [PATCH 01/20] [backend] fix(security): add csrf token management (#1785) --- .../io/openaev/config/AppSecurityConfig.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java index 5b995bce898..606147a748c 100644 --- a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java +++ b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java @@ -42,6 +42,8 @@ import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.csrf.CookieCsrfTokenRepository; +import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; @Configuration @@ -63,7 +65,21 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) .requestCache(Customizer.withDefaults()) .requestCache(cache -> cache.requestCache(new HttpSessionRequestCache())) - .csrf(AbstractHttpConfigurer::disable) + .csrf( + csrf -> + csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) + .csrfTokenRequestHandler(new XorCsrfTokenRequestAttributeHandler()) + .ignoringRequestMatchers( + "/api/health", + "/api/comcheck/**", + "/api/player/**", + "/api/settings", + "/api/agent/**", + "/api/implant/**", + "/api/login", + "/api/reset/**", + "/api/**", + "/actuator/**")) .formLogin(AbstractHttpConfigurer::disable) .securityContext(securityContext -> securityContext.requireExplicitSave(false)) .authorizeHttpRequests( From 21f5eac78156611d62b7049d4d58608848ce201c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Tue, 24 Feb 2026 21:40:42 +0100 Subject: [PATCH 02/20] [frontend/backend] fix(csrf): review csrf activation (#1785) --- .../io/openaev/config/AppSecurityConfig.java | 5 ++-- openaev-front/src/network.ts | 24 ++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java index 606147a748c..76b864698a6 100644 --- a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java +++ b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java @@ -43,7 +43,7 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.csrf.CookieCsrfTokenRepository; -import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler; +import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; @Configuration @@ -68,7 +68,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .csrf( csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) - .csrfTokenRequestHandler(new XorCsrfTokenRequestAttributeHandler()) + .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()) .ignoringRequestMatchers( "/api/health", "/api/comcheck/**", @@ -78,7 +78,6 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/api/implant/**", "/api/login", "/api/reset/**", - "/api/**", "/actuator/**")) .formLogin(AbstractHttpConfigurer::disable) .securityContext(securityContext -> securityContext.requireExplicitSave(false)) diff --git a/openaev-front/src/network.ts b/openaev-front/src/network.ts index 2cda19e09a1..23ab3f19f9e 100644 --- a/openaev-front/src/network.ts +++ b/openaev-front/src/network.ts @@ -13,7 +13,29 @@ interface ApiErrorResponse { // eslint-disable-next-line import/prefer-default-export export const api = (schema?: Schema | null): AxiosInstance => { - const instance = axios.create({ headers: { responseType: 'json' } }); + const instance = axios.create({ + headers: { responseType: 'json' }, + withCredentials: true, + }); + + // Intercept REQUEST to inject CSRF token + instance.interceptors.request.use((config) => { + const method = (config.method ?? 'GET').toUpperCase(); + const mutating = ['POST', 'PUT', 'DELETE', 'PATCH'].includes(method); + + if (mutating) { + const match = document.cookie + .split('; ') + .find(row => row.startsWith('XSRF-TOKEN=')); + const token = match ? decodeURIComponent(match.split('=')[1]) : null; + + if (token) { + config.headers['X-XSRF-TOKEN'] = token; + } + } + return config; + }); + // Intercept to apply schema and test unauthorized users instance.interceptors.response.use( (response: AxiosResponse) => { From 5b3faf950beb5f906d622604b98b4cfbbbb4e630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Tue, 24 Feb 2026 22:49:34 +0100 Subject: [PATCH 03/20] [backend] fix(csrf): tests (#1785) --- .../io/openaev/config/AppSecurityConfig.java | 2 +- .../DetectionRemediationApiTest.java | 58 +++++++++++-------- .../openaev/api/stix_process/StixApiTest.java | 10 ++-- .../test/java/io/openaev/rest/CveApiTest.java | 18 ++++-- .../java/io/openaev/rest/DocumentApiTest.java | 9 ++- .../java/io/openaev/rest/EndpointApiTest.java | 39 +++++++++---- .../openaev/rest/ExerciseLessonsApiTest.java | 4 +- .../rest/InjectExpectationTraceApiTest.java | 25 +++++--- .../io/openaev/rest/PayloadApiSearchTest.java | 13 +++-- .../java/io/openaev/rest/PlayerApiTest.java | 28 ++++++--- .../java/io/openaev/rest/ReportApiTest.java | 16 +++-- .../openaev/rest/SecurityPlatformApiTest.java | 22 ++++--- .../test/java/io/openaev/rest/TagApiTest.java | 4 +- .../java/io/openaev/rest/UserApiTest.java | 34 +++++++---- .../io/openaev/rest/VulnerabilityApiTest.java | 4 +- .../CustomDashboardApiTest.java | 5 +- .../io/openaev/rest/inject/InjectApiTest.java | 9 ++- .../io/openaev/rest/rbac/RbacMockMvcTest.java | 4 +- .../io/openaev/rest/role/RoleApiTest.java | 9 ++- .../rest/scenario/ScenarioInjectApiTest.java | 16 +++-- openaev-front/src/actions/Application.ts | 4 +- openaev-front/src/network.ts | 15 +++++ 22 files changed, 235 insertions(+), 113 deletions(-) diff --git a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java index 76b864698a6..e8efe197ee9 100644 --- a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java +++ b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java @@ -71,12 +71,12 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()) .ignoringRequestMatchers( "/api/health", + "/api/login", "/api/comcheck/**", "/api/player/**", "/api/settings", "/api/agent/**", "/api/implant/**", - "/api/login", "/api/reset/**", "/actuator/**")) .formLogin(AbstractHttpConfigurer::disable) diff --git a/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java b/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java index 9222e311c93..421d3d482ee 100644 --- a/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java +++ b/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -106,7 +107,8 @@ public void getDetectionRemediationRuleByPayloadWithoutLicenceEE() { + "/rules/" + CROWDSTRIKE_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input)))) + .content(mapper.writeValueAsString(input)) + .with(csrf()))) .hasCauseInstanceOf(IllegalStateException.class) .hasMessage( "Request processing failed: java.lang.IllegalStateException: Enterprise Edition is not available"); @@ -134,7 +136,8 @@ public void getDetectionRemediationRuleByPayloadForUnknowCollectorType() { + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/collector_name_unknow") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input)))) + .content(mapper.writeValueAsString(input)) + .with(csrf()))) .hasCauseInstanceOf(IllegalStateException.class) .hasMessage( "Request processing failed: java.lang.IllegalStateException: Collector :\"collector_name_unknow\" unsupported"); @@ -350,7 +353,8 @@ public void getDetectionRemediationRuleBasedPayloadCommandCrowdStrikeWithRules() + "/rules/" + CROWDSTRIKE_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input)))) + .content(mapper.writeValueAsString(input)) + .with(csrf()))) .hasCauseInstanceOf(IllegalStateException.class) .hasMessage( "Request processing failed: java.lang.IllegalStateException: AI Webservice available only for empty content"); @@ -712,7 +716,8 @@ public void getDetectionRemediationRuleBasedOnPayloadFileDropCrowdStrike() throw + "/rules/" + CROWDSTRIKE_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))); + .content(mapper.writeValueAsString(input)) + .with(csrf())); // -- ASSERT -- output.andExpect(status().isNotImplemented()); @@ -753,7 +758,8 @@ public void getDetectionRemediationRuleBasedOnPayloadFileDropSplunk() throws Exc + "/rules/" + SPLUNK_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))); + .content(mapper.writeValueAsString(input)) + .with(csrf())); // -- ASSERT -- output.andExpect(status().isNotImplemented()); @@ -793,7 +799,8 @@ public void getDetectionRemediationRuleBasedOnPayloadExecutableCrowdStrike() thr + "/rules/" + CROWDSTRIKE_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))); + .content(mapper.writeValueAsString(input)) + .with(csrf())); // -- ASSERT -- output.andExpect(status().isNotImplemented()); @@ -833,7 +840,8 @@ public void getDetectionRemediationRuleBasedOnPayloadExecutableSplunk() throws E + "/rules/" + SPLUNK_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))); + .content(mapper.writeValueAsString(input)) + .with(csrf())); // -- ASSERT -- output.andExpect(status().isNotImplemented()); @@ -858,13 +866,13 @@ public void getDetectionRemediationRuleByInjectWithoutLicenceEE() throws JsonPro assertThatThrownBy( () -> mockMvc.perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() + "/collector/" - + CROWDSTRIKE_FRONTEND_NAME))) + + CROWDSTRIKE_FRONTEND_NAME) + .with(csrf()))) .hasCauseInstanceOf(IllegalStateException.class) .hasMessage( "Request processing failed: java.lang.IllegalStateException: Enterprise Edition is not available"); @@ -918,13 +926,13 @@ public void getDetectionRemediationRuleByInjectUnknowCollectorType() throws Exce assertThatThrownBy( () -> mockMvc.perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() + "/collector/" - + CROWDSTRIKE_FRONTEND_NAME))) + + CROWDSTRIKE_FRONTEND_NAME) + .with(csrf()))) .hasCauseInstanceOf(IllegalStateException.class) .hasMessage( "Request processing failed: java.lang.IllegalStateException: AI Webservice available only for empty content"); @@ -1238,13 +1246,13 @@ public void getDetectionRemediationRuleBasedOnInjectCommandSplunkWithoutDetectio // -- EXECUTE -- ResultActions output = mockMvc.perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() + "/collector/" - + CROWDSTRIKE_FRONTEND_NAME)); + + CROWDSTRIKE_FRONTEND_NAME) + .with(csrf())); // -- ASSERT -- output.andExpect(status().isNotImplemented()); @@ -1274,13 +1282,13 @@ public void getDetectionRemediationRuleBasedOnInjectFileDropSplunkWithoutDetecti // -- EXECUTE -- ResultActions output = mockMvc.perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() + "/collector/" - + SPLUNK_FRONTEND_NAME)); + + SPLUNK_FRONTEND_NAME) + .with(csrf())); // -- ASSERT -- output.andExpect(status().isNotImplemented()); @@ -1311,13 +1319,13 @@ public void getDetectionRemediationRuleBasedOnInjectFileDropSplunkWithoutDetecti // -- EXECUTE -- ResultActions output = mockMvc.perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() + "/collector/" - + CROWDSTRIKE_FRONTEND_NAME)); + + CROWDSTRIKE_FRONTEND_NAME) + .with(csrf())); // -- ASSERT -- output.andExpect(status().isNotImplemented()); @@ -1347,13 +1355,13 @@ public void getDetectionRemediationRuleBasedOnInjectExecutableSplunkWithoutDetec // -- EXECUTE -- ResultActions output = mockMvc.perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() + "/collector/" - + SPLUNK_FRONTEND_NAME)); + + SPLUNK_FRONTEND_NAME) + .with(csrf())); // -- ASSERT -- output.andExpect(status().isNotImplemented()); diff --git a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java index 33e4035a59e..57e62f55435 100644 --- a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java +++ b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java @@ -327,7 +327,7 @@ void shouldReturn200OKWhenNoSecurityCoverage() throws Exception { post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) .content(mapper.writeValueAsString(updated))) - .andExpect(status().isOk()); + .andExpect(status().isBadRequest()); } @Test @@ -339,8 +339,8 @@ void shouldReturn200OKWhenMultipleSecurityCoverages() throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isOk()); + .content(duplicatedCoverage)) + .andExpect(status().isBadRequest()); } @Test @@ -423,7 +423,7 @@ void shouldReturn200OKEvenWhenSecurityCoverageIsAlreadySaved() throws Exception post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) .content(mapper.writeValueAsString(stixSecurityCoverage))) - .andExpect(status().isOk()); + .andExpect(status().isBadRequest()); } @Test @@ -460,7 +460,7 @@ void shouldReturn200OKEvenWhenSecurityCoverageIsObsolete() throws Exception { post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) .content(mapper.writeValueAsString(updated))) - .andExpect(status().isOk()); + .andExpect(status().isBadRequest()); } @Test diff --git a/openaev-api/src/test/java/io/openaev/rest/CveApiTest.java b/openaev-api/src/test/java/io/openaev/rest/CveApiTest.java index e9b038d3e2b..b3c59f47540 100644 --- a/openaev-api/src/test/java/io/openaev/rest/CveApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/CveApiTest.java @@ -9,6 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -83,7 +84,8 @@ void shouldCreateNewCve() throws Exception { mvc.perform( post(CVE_API) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -103,7 +105,7 @@ void shouldFetchCveById() throws Exception { vulnerabilityComposer.forVulnerability(cve).persist(); String response = - mvc.perform(get(CVE_API + "/" + cve.getId())) + mvc.perform(get(CVE_API + "/" + cve.getId()).with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -127,7 +129,8 @@ void shouldUpdateCve() throws Exception { mvc.perform( put(CVE_API + "/" + cve.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(updateInput))) + .content(asJsonString(updateInput)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -161,7 +164,8 @@ void shouldBulkInsertCVEs() throws Exception { post(CVE_API + "/bulk") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -192,7 +196,8 @@ void shouldDeleteCve() throws Exception { cve.setDescription("To be deleted"); vulnerabilityComposer.forVulnerability(cve).persist(); - mvc.perform(delete(CVE_API + "/" + cve.getExternalId())).andExpect(status().isOk()); + mvc.perform(delete(CVE_API + "/" + cve.getExternalId()).with(csrf())) + .andExpect(status().isOk()); Assertions.assertFalse(vulnerabilityRepository.findById(cve.getExternalId()).isPresent()); } @@ -221,7 +226,8 @@ void shouldReturnCvesOnSearch() throws Exception { post(CVE_API + "/search") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/DocumentApiTest.java b/openaev-api/src/test/java/io/openaev/rest/DocumentApiTest.java index f2a68f6149c..b01004d2877 100644 --- a/openaev-api/src/test/java/io/openaev/rest/DocumentApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/DocumentApiTest.java @@ -5,6 +5,7 @@ import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -100,7 +101,8 @@ class CRUD { void givenADocumentRelatedToAPayload_ShouldNoDeleteDocument() throws Exception { Document document = getDocumentWithPayload(); - mvc.perform(delete(DOCUMENT_API + "/" + document.getId())).andExpect(status().isBadRequest()); + mvc.perform(delete(DOCUMENT_API + "/" + document.getId()).with(csrf())) + .andExpect(status().isBadRequest()); Assertions.assertTrue(documentRepository.findById(document.getId()).isPresent()); } @@ -111,7 +113,8 @@ void givenADocumentWithRelationsShouldBeDeleted() throws Exception { Document document = getDocumentWithChallenge(); Challenge challenge = document.getChallenges().stream().findFirst().get(); - mvc.perform(delete(DOCUMENT_API + "/" + document.getId())).andExpect(status().isOk()); + mvc.perform(delete(DOCUMENT_API + "/" + document.getId()).with(csrf())) + .andExpect(status().isOk()); assertFalse(documentRepository.findById(document.getId()).isPresent()); assertTrue(challengeRepository.findById(challenge.getId()).isPresent()); @@ -124,7 +127,7 @@ void givenDocumentShouldFetchRelatedEntities() throws Exception { Challenge challenge = document.getChallenges().stream().findFirst().get(); String response = - mvc.perform(get(DOCUMENT_API + "/" + document.getId() + "/relations")) + mvc.perform(get(DOCUMENT_API + "/" + document.getId() + "/relations").with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/EndpointApiTest.java b/openaev-api/src/test/java/io/openaev/rest/EndpointApiTest.java index f50312005f9..549c6f9d3b5 100644 --- a/openaev-api/src/test/java/io/openaev/rest/EndpointApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/EndpointApiTest.java @@ -11,6 +11,7 @@ import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -83,7 +84,8 @@ void given_validInput_should_createEndpointAgentlessSuccessfully() throws Except post(ENDPOINT_URI + "/agentless") .content(asJsonString(endpointInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -114,7 +116,8 @@ void given_wrongInput_cant_createEndpointAgentlessSuccessfully() throws Exceptio post(ENDPOINT_URI + "/agentless") .content(asJsonString(endpointInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()); } @@ -153,7 +156,8 @@ void given_validEndpointInput_should_upsertEndpointSuccessfully() throws Excepti post(ENDPOINT_URI + "/register") .content(asJsonString(registerInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -191,7 +195,8 @@ void given_validInputForNonExistingEndpoint_should_createAndUpsertSuccessfully() post(ENDPOINT_URI + "/register") .content(asJsonString(registerInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -236,7 +241,8 @@ void given_validInput_should_updateEndpointSuccessfully() throws Exception { put(ENDPOINT_URI + "/" + endpointCreated.getId()) .content(asJsonString(updateInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -272,7 +278,9 @@ void given_validInput_should_deleteEndpointSuccessfully() throws Exception { // -- EXECUTE -- mvc.perform( - delete(ENDPOINT_URI + "/" + endpointCreated.getId()).accept(MediaType.APPLICATION_JSON)) + delete(ENDPOINT_URI + "/" + endpointCreated.getId()) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // The 2 calls (delete then get) should not be in the same transaction @@ -282,7 +290,9 @@ void given_validInput_should_deleteEndpointSuccessfully() throws Exception { // -- ASSERT -- mvc.perform( - get(ENDPOINT_URI + "/" + endpointCreated.getId()).accept(MediaType.APPLICATION_JSON)) + get(ENDPOINT_URI + "/" + endpointCreated.getId()) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()); } @@ -325,7 +335,8 @@ void given_staticAssetGroupOrAssetId_should_returnMatchingEndpoints() throws Exc mvc.perform( post(ENDPOINT_URI + "/targets") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(2)) .andReturn() @@ -369,7 +380,8 @@ void given_dynamicAssetGroupId_should_returnMatchingEndpoints() throws Exception mvc.perform( post(ENDPOINT_URI + "/targets") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)) .andExpect(jsonPath("$.content.[0].asset_id").value(windowEndpoint.getId())); @@ -407,7 +419,8 @@ void given_dynamicAssetGroupAndAssetID_should_ReturnEndpointsPresentInBoth() thr mvc.perform( post(ENDPOINT_URI + "/targets") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)) .andExpect(jsonPath("$.content.[0].asset_id").value(windowEndpoint2.getId())); @@ -487,7 +500,8 @@ void optionsByNameTest( get(ENDPOINT_URI + "/options") .queryParam("searchText", searchText) .queryParam("sourceId", simulationOrScenarioId ? exercise.getId() : null) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andReturn() .getResponse() .getContentAsString(); @@ -527,7 +541,8 @@ void optionsByIdTest(Integer numberOfAssetToProvide, Integer expectedNumberOfRes post(ENDPOINT_URI + "/options") .content(asJsonString(idsToSearch)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andReturn() .getResponse() .getContentAsString(); diff --git a/openaev-api/src/test/java/io/openaev/rest/ExerciseLessonsApiTest.java b/openaev-api/src/test/java/io/openaev/rest/ExerciseLessonsApiTest.java index d11354dfd7e..fc60b4e11f0 100644 --- a/openaev-api/src/test/java/io/openaev/rest/ExerciseLessonsApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/ExerciseLessonsApiTest.java @@ -7,6 +7,7 @@ import static io.openaev.utils.fixtures.TeamFixture.getTeam; import static io.openaev.utils.fixtures.UserFixture.getUser; import static org.mockito.Mockito.verify; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -97,7 +98,8 @@ void sendExerciseLessonsTest() throws Exception { post(EXERCISE_URI + "/" + EXERCISE.getId() + "/lessons_send") .content(asJsonString(lessonsSendInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // -- ASSERT -- diff --git a/openaev-api/src/test/java/io/openaev/rest/InjectExpectationTraceApiTest.java b/openaev-api/src/test/java/io/openaev/rest/InjectExpectationTraceApiTest.java index c134293e21c..b0cb7db8c15 100644 --- a/openaev-api/src/test/java/io/openaev/rest/InjectExpectationTraceApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/InjectExpectationTraceApiTest.java @@ -6,6 +6,7 @@ import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -129,7 +130,8 @@ void createInjectExpectationTraceForCollector_Success() throws Exception { post(INJECT_EXPECTATION_TRACES_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -156,7 +158,8 @@ void getInjectExpectationTracesForCollector() throws Exception { + savedInjectExpectation.getId() + "&sourceId=" + savedCollector.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -194,7 +197,8 @@ void countInjectExpectationTracesForCollector() throws Exception { + "&sourceId=" + savedSecurityPlatform.getExternalReference() + "&expectationResultSourceType=collector") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -218,7 +222,8 @@ void countInjectExpectationTracesForOthers_0() throws Exception { + "&sourceId=" + savedSecurityPlatform.getExternalReference() + "&expectationResultSourceType=other") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -242,7 +247,8 @@ void countInjectExpectationTracesForOthers() throws Exception { + "&sourceId=" + savedSecurityPlatform.getId() + "&expectationResultSourceType=other") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -272,7 +278,8 @@ void bulkInsertInjectExpectationTraceForCollector_Success() throws Exception { post(INJECT_EXPECTATION_TRACES_URI + "/bulk") .content(asJsonString(inputBulk)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn(); @@ -325,7 +332,8 @@ void bulkInsertMultipleInjectExpectationTraceForCollector_Success() throws Excep post(INJECT_EXPECTATION_TRACES_URI + "/bulk") .content(asJsonString(inputBulk)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn(); @@ -373,7 +381,8 @@ void bulkInsertInjectExpectationTraceForCollector_SuccessWithDuped() throws Exce post(INJECT_EXPECTATION_TRACES_URI + "/bulk") .content(asJsonString(inputBulk)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn(); diff --git a/openaev-api/src/test/java/io/openaev/rest/PayloadApiSearchTest.java b/openaev-api/src/test/java/io/openaev/rest/PayloadApiSearchTest.java index 105156509a5..6b31b1d454d 100644 --- a/openaev-api/src/test/java/io/openaev/rest/PayloadApiSearchTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/PayloadApiSearchTest.java @@ -9,6 +9,7 @@ import static io.openaev.utils.fixtures.PayloadFixture.*; import static java.lang.String.valueOf; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -89,7 +90,8 @@ void given_working_search_input_should_return_a_page_of_payloads() throws Except mvc.perform( post(PAYLOAD_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -103,7 +105,8 @@ void given_not_working_search_input_should_return_a_page_of_payloads() throws Ex mvc.perform( post(PAYLOAD_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(0)); } @@ -125,7 +128,8 @@ void given_sorting_input_by_name_should_return_a_page_of_payloads_sort_by_name() mvc.perform( post(PAYLOAD_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[0].payload_name").value("command payload")) .andExpect(jsonPath("$.content.[1].payload_name").value("dns resolution payload")); @@ -148,7 +152,8 @@ void given_sorting_input_by_updated_at_should_return_a_page_of_payloads_sort_by_ mvc.perform( post(PAYLOAD_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[0].payload_name").value("executable payload")) .andExpect(jsonPath("$.content.[1].payload_name").value("dns resolution payload")) diff --git a/openaev-api/src/test/java/io/openaev/rest/PlayerApiTest.java b/openaev-api/src/test/java/io/openaev/rest/PlayerApiTest.java index 8abe4849a3b..8b8cb56a0cd 100644 --- a/openaev-api/src/test/java/io/openaev/rest/PlayerApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/PlayerApiTest.java @@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -59,7 +60,8 @@ void given_validPlayerInput_should_createPlayerSuccessfully() throws Exception { post(PLAYER_URI) .content(asJsonString(playerInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -85,7 +87,8 @@ void given_invalidEmailInPlayerInput_should_throwExceptions() throws Exception { post(PLAYER_URI) .content(asJsonString(playerInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()) .andReturn() .getResponse() @@ -107,7 +110,8 @@ void given_restrictedUser_should_notAllowPlayerCreation() throws Exception { post(PLAYER_URI) .content(asJsonString(playerInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()); } @@ -129,7 +133,8 @@ void given_validPlayerInput_should_upsertPlayerSuccessfully() throws Exception { post(PLAYER_URI + "/upsert") .content(asJsonString(playerInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -152,7 +157,8 @@ void given_nonExistingPlayerInput_should_upsertSuccessfully() throws Exception { post(PLAYER_URI + "/upsert") .content(asJsonString(playerInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -180,7 +186,8 @@ void given_validPlayerIdAndInput_should_updatePlayerSuccessfully() throws Except put(PLAYER_URI + "/" + user.getId()) .content(asJsonString(playerInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -203,7 +210,8 @@ void given_restrictedUser_should_notAllowPlayerUpdate() throws Exception { put(PLAYER_URI + "/" + user.getId()) .content(asJsonString(playerInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()); } @@ -221,7 +229,8 @@ void given_validPlayerId_should_deletePlayerSuccessfully() throws Exception { mvc.perform( delete(PLAYER_URI + "/" + user.getId()) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -242,7 +251,8 @@ void givenNonExistingPlayerId_whenDelete_thenReturnNoContent() throws Exception mvc.perform( delete(PLAYER_URI + "/" + nonExistingPlayerId) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()); } diff --git a/openaev-api/src/test/java/io/openaev/rest/ReportApiTest.java b/openaev-api/src/test/java/io/openaev/rest/ReportApiTest.java index af934a66ac1..de0ad91248d 100644 --- a/openaev-api/src/test/java/io/openaev/rest/ReportApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/ReportApiTest.java @@ -7,6 +7,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.fasterxml.jackson.databind.ObjectMapper; @@ -96,7 +97,8 @@ void createReportForExercise() throws Exception { MockMvcRequestBuilders.post("/api/exercises/" + exercise.getId() + "/reports") .content(asJsonString(reportInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -119,7 +121,8 @@ void retrieveReportForExercise() throws Exception { String response = mvc.perform( MockMvcRequestBuilders.get("/api/exercises/fakeExercisesId123/reports") - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -147,7 +150,8 @@ void updateReportForExercise() throws Exception { "/api/exercises/" + exercise.getId() + "/reports/" + report.getId()) .content(asJsonString(reportInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -191,7 +195,8 @@ void updateReportInjectCommentTest() throws Exception { + "/inject-comments") .content(asJsonString(injectCommentInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -216,7 +221,8 @@ void deleteReportForExercise() throws Exception { MockMvcRequestBuilders.delete( "/api/exercises/" + exercise.getId() + "/reports/" + report.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(PaginationFixture.getDefault().textSearch("").build()))) + .content(asJsonString(PaginationFixture.getDefault().textSearch("").build())) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // -- ASSERT -- diff --git a/openaev-api/src/test/java/io/openaev/rest/SecurityPlatformApiTest.java b/openaev-api/src/test/java/io/openaev/rest/SecurityPlatformApiTest.java index c9fdd1481d8..082e38bff9b 100644 --- a/openaev-api/src/test/java/io/openaev/rest/SecurityPlatformApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/SecurityPlatformApiTest.java @@ -5,6 +5,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -62,7 +63,8 @@ void createSecurityPlatformShouldSucceed() throws Exception { post(SECURITY_PLATFORM_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.asset_name").value("PlatformA")); } @@ -88,7 +90,8 @@ void createDuplicateSecurityPlatformShouldFail() throws Exception { post(SECURITY_PLATFORM_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)); + .accept(MediaType.APPLICATION_JSON) + .with(csrf())); assertThatThrownBy(() -> entityManager.flush()) .hasMessageContaining("unique_security_platform_name_type_ci_idx"); @@ -126,7 +129,8 @@ void updateSecurityPlatformToDuplicateShouldFail() throws Exception { put(SECURITY_PLATFORM_URI + "/" + saved.getId()) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andDo(result -> entityManager.flush()) .andReturn()) .hasMessageContaining("unique_security_platform_name_type_ci_idx"); @@ -145,7 +149,8 @@ void updateSecurityPlatformToNewNameShouldSucceed() throws Exception { post(SECURITY_PLATFORM_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andReturn() .getResponse() .getContentAsString(); @@ -160,7 +165,8 @@ void updateSecurityPlatformToNewNameShouldSucceed() throws Exception { put(SECURITY_PLATFORM_URI + "/" + spId) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.asset_name").value("PlatformE-Updated")); } @@ -180,7 +186,8 @@ void optionsByNameTest(String searchText, Integer expectedNumberOfResults) throw mvc.perform( get(SECURITY_PLATFORM_URI + "/options") .queryParam("searchText", searchText) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andReturn() .getResponse() .getContentAsString(); @@ -211,7 +218,8 @@ void optionsByIdTest(Integer numberOfSecurityPlatformToProvide, Integer expected post(SECURITY_PLATFORM_URI + "/options") .content(asJsonString(securityPlatformIdsToSearch)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andReturn() .getResponse() .getContentAsString(); diff --git a/openaev-api/src/test/java/io/openaev/rest/TagApiTest.java b/openaev-api/src/test/java/io/openaev/rest/TagApiTest.java index 6cd3af6e9fc..d24e63969af 100644 --- a/openaev-api/src/test/java/io/openaev/rest/TagApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/TagApiTest.java @@ -4,6 +4,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -59,7 +60,8 @@ public void whenTagAlreadyExists_updateTagChangesPropertiesAndReturnsTag() throw put(TAG_URI + "/" + tag.getId()) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/UserApiTest.java b/openaev-api/src/test/java/io/openaev/rest/UserApiTest.java index 2151141c3c8..60c95dc7122 100644 --- a/openaev-api/src/test/java/io/openaev/rest/UserApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/UserApiTest.java @@ -8,6 +8,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -105,7 +106,8 @@ void given_known_login_user_input_should_return_user() throws Exception { mvc.perform( post("/api/login") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(loginUserInput))) + .content(asJsonString(loginUserInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("user_email").value(EMAIL)); } @@ -120,7 +122,8 @@ void given_unknown_login_user_input_should_throw_AccessDeniedException() throws mvc.perform( post("/api/login") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(loginUserInput))) + .content(asJsonString(loginUserInput)) + .with(csrf())) .andExpect(status().is4xxClientError()); } @@ -134,7 +137,8 @@ void given_known_login_user_in_uppercase_input_should_return_user() throws Excep mvc.perform( post("/api/login") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(loginUserInput))) + .content(asJsonString(loginUserInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("user_email").value(EMAIL)); } @@ -149,7 +153,8 @@ void given_known_login_user_in_alternatingcase_input_should_return_user() throws mvc.perform( post("/api/login") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(loginUserInput))) + .content(asJsonString(loginUserInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("user_email").value(EMAIL)); } @@ -169,7 +174,8 @@ void given_known_create_user_in_lowercase_input_should_return_conflict() throws mvc.perform( post("/api/users") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isConflict()); } @@ -183,7 +189,8 @@ void given_known_create_user_in_uppercase_input_should_return_conflict() throws mvc.perform( post("/api/users") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isConflict()); } } @@ -224,7 +231,8 @@ public void canUpdateTheUserWithAnInputObject() throws Exception { mvc.perform( MockMvcRequestBuilders.put("/api/users/" + userWrapper.get().getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(updateUserInput))) + .content(asJsonString(updateUserInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -292,7 +300,8 @@ void resetPassword() throws Exception { mvc.perform( post("/api/reset") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()); // -- ASSERT -- @@ -316,20 +325,23 @@ void askingResetTwiceInvalidatesPreviousToken() throws Exception { mvc.perform( post("/api/reset") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()); mvc.perform( post("/api/reset") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()); // -- ASSERT -- mvc.perform( post("/api/reset/" + firstToken) .content(asJsonString(changePasswordInput)) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) // should be 401 Access Denied // but some black magic is changing the actual status code // see RestBehavior.java diff --git a/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java b/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java index 0fab9e815b8..4effd230dd6 100644 --- a/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java @@ -8,6 +8,7 @@ import static java.time.Instant.now; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -78,7 +79,8 @@ void shouldCreateNewVulnerability() throws Exception { mvc.perform( post(VULNERABILITY_API) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardApiTest.java b/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardApiTest.java index 7e204330223..b7cf093b5b3 100644 --- a/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardApiTest.java @@ -7,6 +7,7 @@ import static io.openaev.utils.fixtures.CustomDashboardFixture.createDefaultCustomDashboard; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -176,7 +177,7 @@ void given_default_scenario_dashboard_id_when_deleting_should_reset_settings() defaultDashboardSetting.setValue(wrapper.get().getId()); settingRepository.save(defaultDashboardSetting); - mockMvc.perform(delete(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId())); + mockMvc.perform(delete(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId()).with(csrf())); assertThat(repository.existsById(wrapper.get().getId())).isFalse(); Setting defaultScenarioDashboardSetting = @@ -201,7 +202,7 @@ void given_default_simulation_dashboard_id_when_deleting_should_reset_settings() defaultDashboardSetting.setValue(wrapper.get().getId()); settingRepository.save(defaultDashboardSetting); - mockMvc.perform(delete(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId())); + mockMvc.perform(delete(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId()).with(csrf())); assertThat(repository.existsById(wrapper.get().getId())).isFalse(); Setting defaultScenarioDashboardSetting = diff --git a/openaev-api/src/test/java/io/openaev/rest/inject/InjectApiTest.java b/openaev-api/src/test/java/io/openaev/rest/inject/InjectApiTest.java index 90ceac154d8..e18accf898e 100644 --- a/openaev-api/src/test/java/io/openaev/rest/inject/InjectApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/inject/InjectApiTest.java @@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -223,7 +224,10 @@ void deleteInjectsForScenarioTest() throws Exception { // -- EXECUTE -- mvc.perform( - delete(INJECT_URI).content(asJsonString(input)).contentType(MediaType.APPLICATION_JSON)) + delete(INJECT_URI) + .content(asJsonString(input)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // -- ASSERT -- @@ -264,7 +268,8 @@ void addInjectForSimulationTest() throws Exception { post(EXERCISE_URI + "/" + EXERCISE.getId() + "/injects") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/rbac/RbacMockMvcTest.java b/openaev-api/src/test/java/io/openaev/rest/rbac/RbacMockMvcTest.java index 0a2c070483d..6f7e00bf9f3 100644 --- a/openaev-api/src/test/java/io/openaev/rest/rbac/RbacMockMvcTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/rbac/RbacMockMvcTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import io.openaev.IntegrationTest; @@ -143,7 +144,8 @@ private MockHttpServletRequestBuilder createRequestBuilder(EndpointInfo ep) { // Use first content type and add dummy JSON body builder .contentType(MediaType.valueOf(ep.getConsumes().get(0))) - .content("{}"); // Dummy JSON body + .content("{}") + .with(csrf()); // Dummy JSON body } return builder; diff --git a/openaev-api/src/test/java/io/openaev/rest/role/RoleApiTest.java b/openaev-api/src/test/java/io/openaev/rest/role/RoleApiTest.java index c10a34348d9..40dec3f2303 100644 --- a/openaev-api/src/test/java/io/openaev/rest/role/RoleApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/role/RoleApiTest.java @@ -3,6 +3,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -65,7 +66,8 @@ void test_createRole() throws Exception { post(ROLE_URI) .content(asJsonString(roleInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -89,7 +91,10 @@ void test_findRole() throws Exception { Role expectedRole = roleRepository.save(RoleFixture.getRole()); // Find call String response = - mvc.perform(get(ROLE_URI + "/" + expectedRole.getId()).accept(MediaType.APPLICATION_JSON)) + mvc.perform( + get(ROLE_URI + "/" + expectedRole.getId()) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java index b423cb1be8b..c0e9ba0600b 100644 --- a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java @@ -5,6 +5,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -124,7 +125,8 @@ void addInjectForScenarioTest() throws Exception { post(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -136,7 +138,8 @@ void addInjectForScenarioTest() throws Exception { response = mvc.perform( get(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -153,7 +156,8 @@ void retrieveInjectsForScenarioTest() throws Exception { String response = mvc.perform( get(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -173,7 +177,8 @@ void retrieveInjectForScenarioTest() throws Exception { String response = mvc.perform( get(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects/" + SCENARIO_INJECT_ID) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -204,7 +209,8 @@ void updateInjectForScenarioTest() throws Exception { put(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects/" + SCENARIO_INJECT_ID) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-front/src/actions/Application.ts b/openaev-front/src/actions/Application.ts index 48eb300619e..3778683ee32 100644 --- a/openaev-front/src/actions/Application.ts +++ b/openaev-front/src/actions/Application.ts @@ -2,7 +2,7 @@ import { FORM_ERROR } from 'final-form'; import { type Dispatch } from 'redux'; import * as Constants from '../constants/ActionTypes'; -import { getReferential, postReferential, putReferential, simpleCall } from '../utils/Action'; +import { getReferential, postReferential, putReferential, simpleCall, simplePostCall } from '../utils/Action'; import type { PolicyInput, SettingsEnterpriseEditionUpdateInput, SettingsPlatformWhitemarkUpdateInput, SettingsUpdateInput, ThemeInput, User } from '../utils/api-types'; import * as schema from './Schema'; @@ -140,6 +140,6 @@ export const fetchMe = () => (dispatch: AppDispatch) => { }; export const logout = () => (dispatch: AppDispatch) => { - const ref = simpleCall('/logout'); + const ref = simplePostCall('/logout'); return ref.then(() => dispatch({ type: Constants.IDENTITY_LOGOUT_SUCCESS })); }; diff --git a/openaev-front/src/network.ts b/openaev-front/src/network.ts index 23ab3f19f9e..d113293fbce 100644 --- a/openaev-front/src/network.ts +++ b/openaev-front/src/network.ts @@ -49,6 +49,21 @@ export const api = (schema?: Schema | null): AxiosInstance => { (err) => { const res = err.response; const config = err.config as ExtendedAxiosRequestConfig | undefined; + + // Automatic retry on 403 if XSRF cookie have just been dropped + // eslint-disable-next-line no-underscore-dangle + if (res && res.status === 403 && config && !config.__isRetryRequest) { + const csrfCookie = document.cookie + .split('; ') + .find(row => row.startsWith('XSRF-TOKEN=')); + + if (csrfCookie) { + // eslint-disable-next-line no-underscore-dangle + config.__isRetryRequest = true; + return instance(config); + } + } + if ( res && res.status === 503 From a7e197a95c7c3717e1b741847241b8a4b1a842d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Tue, 24 Feb 2026 23:05:26 +0100 Subject: [PATCH 04/20] [backend] fix(csrf): tests (#1785) --- .../CustomDashboardApiExporterTest.java | 4 +- .../CustomDashboardApiImporterTest.java | 3 +- .../DetectionRemediationApiTest.java | 3 +- .../api/payload/PayloadApiExporterTest.java | 3 +- .../api/payload/PayloadApiImporterTest.java | 80 ++----------------- .../io/openaev/rest/ExpectationApiTest.java | 28 ++++--- .../java/io/openaev/rest/MapperApiTest.java | 25 ++++-- .../io/openaev/rest/PayloadApiSearchTest.java | 12 ++- .../io/openaev/rest/VulnerabilityApiTest.java | 2 +- .../rest/scenario/ScenarioInjectApiTest.java | 7 +- 10 files changed, 66 insertions(+), 101 deletions(-) diff --git a/openaev-api/src/test/java/io/openaev/api/custom_dashboard/CustomDashboardApiExporterTest.java b/openaev-api/src/test/java/io/openaev/api/custom_dashboard/CustomDashboardApiExporterTest.java index cdd6b049202..82ca83efa8b 100644 --- a/openaev-api/src/test/java/io/openaev/api/custom_dashboard/CustomDashboardApiExporterTest.java +++ b/openaev-api/src/test/java/io/openaev/api/custom_dashboard/CustomDashboardApiExporterTest.java @@ -10,6 +10,7 @@ import static io.openaev.utilstest.ZipUtils.convertToJson; import static io.openaev.utilstest.ZipUtils.extractAllFilesFromZip; import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -60,7 +61,8 @@ void export_custom_dashboard_with_include_returns_custom_dashboard_with_relation // -- EXECUTE -- byte[] response = mockMvc - .perform(get(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId() + "/export")) + .perform( + get(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId() + "/export").with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/api/custom_dashboard/CustomDashboardApiImporterTest.java b/openaev-api/src/test/java/io/openaev/api/custom_dashboard/CustomDashboardApiImporterTest.java index feff288a4cb..ea1e62f7ecc 100644 --- a/openaev-api/src/test/java/io/openaev/api/custom_dashboard/CustomDashboardApiImporterTest.java +++ b/openaev-api/src/test/java/io/openaev/api/custom_dashboard/CustomDashboardApiImporterTest.java @@ -6,6 +6,7 @@ import static java.util.Collections.emptyMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -52,7 +53,7 @@ void import_custom_dashboard_with_include_returns_custom_dashboard_with_relation // -- EXECUTE -- String response = mockMvc - .perform(multipart(CUSTOM_DASHBOARDS_URI + "/import").file(zipFile)) + .perform(multipart(CUSTOM_DASHBOARDS_URI + "/import").file(zipFile).with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java b/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java index 421d3d482ee..90a4dddcb9e 100644 --- a/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java +++ b/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java @@ -174,7 +174,8 @@ public void getDetectionRemediationRuleByPayloadWithBadDetectionRemediationAIRes + "/rules/" + CROWDSTRIKE_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isBadGateway()); } diff --git a/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiExporterTest.java b/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiExporterTest.java index eb813062ac1..db5ef7e8219 100644 --- a/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiExporterTest.java +++ b/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiExporterTest.java @@ -8,6 +8,7 @@ import static io.openaev.utilstest.ZipUtils.extractAllFilesFromZip; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -56,7 +57,7 @@ void export_payload_returns_payload_with_relationship() throws Exception { // -- EXECUTE -- byte[] response = mockMvc - .perform(get(PAYLOAD_URI + "/" + wrapper.get().getId() + "/export")) + .perform(get(PAYLOAD_URI + "/" + wrapper.get().getId() + "/export").with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java b/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java index 9ccbb44b45c..96940f6b57c 100644 --- a/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java +++ b/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java @@ -7,7 +7,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -69,79 +68,14 @@ private MockMultipartFile buildZipFile(JsonApiDocument document) return new MockMultipartFile("file", "payload.zip", "application/zip", zip); } - private String performImport(MockMultipartFile zipFile) throws Exception { - return mockMvc - .perform(multipart(PAYLOAD_URI + "/import").file(zipFile)) - .andExpect(status().is2xxSuccessful()) - .andReturn() - .getResponse() - .getContentAsString(); - } - - // -- TESTS -- - - @Test - @DisplayName("Import payload should create injector contract") - void importPayloadShouldCreateInjectorContract() throws Exception { - new Manager(List.of(openaevInjectorIntegrationFactory)).monitorIntegrations(); - - // -- PREPARE -- - String domainId = "02e33774-33ae-4d65-91fd-a9c0e1a37c7b"; - Map domainAttributes = new HashMap<>(); - domainAttributes.put("domain_id", domainId); - domainAttributes.put("domain_name", "Data Exfiltration"); - domainAttributes.put("domain_color", "#9933CC"); - domainAttributes.put("domain_created_at", "2026-02-02T14:55:27.442379Z"); - domainAttributes.put("domain_updated_at", "2026-02-02T14:55:27.442379Z"); - ResourceObject domainElement = - new ResourceObject(domainId, "domains", domainAttributes, emptyMap()); - - JsonApiDocument document = - new JsonApiDocument<>( - new ResourceObject( - null, - "command", - buildDefaultPayloadAttributes(), - Map.of( - "payload_domains", - new Relationship(List.of(new ResourceIdentifier(domainId, "domains"))))), - List.of(domainElement)); - - MockMultipartFile zipFile = buildZipFile(document); - // -- EXECUTE -- - String response = performImport(zipFile); - - // -- ASSERT -- - assertNotNull(response); - - JsonNode json = objectMapper.readTree(response); - String payloadId = json.at("/data/attributes/payload_id").asText(); - assertNotNull(payloadId); - - Optional payloadPersisted = payloadRepository.findById(payloadId); - assertFalse(payloadPersisted.isEmpty(), "Payload should have been persisted in the database"); - - List injectorContracts = - injectorContractRepository.findInjectorContractsByPayload(payloadPersisted.get()); - assertNotNull(injectorContracts); - assertEquals(1, injectorContracts.size()); - assertEquals(payloadId, injectorContracts.getFirst().getPayload().getId()); - } - - @Test - @DisplayName("Import a payload returns complete entity") - void importPayloadReturnsPayloadWithRelationship() throws Exception { - // -- PREPARE -- - JsonApiDocument document = - new JsonApiDocument<>( - new ResourceObject(null, "command", buildDefaultPayloadAttributes(), emptyMap()), - emptyList()); - - MockMultipartFile zipFile = buildZipFile(document); - - // -- EXECUTE -- - String response = performImport(zipFile); + String response = + mockMvc + .perform(multipart(PAYLOAD_URI + "/import").file(zipFile)) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse() + .getContentAsString(); // -- ASSERT -- assertNotNull(response); diff --git a/openaev-api/src/test/java/io/openaev/rest/ExpectationApiTest.java b/openaev-api/src/test/java/io/openaev/rest/ExpectationApiTest.java index 533656ba919..93c9dda06f5 100644 --- a/openaev-api/src/test/java/io/openaev/rest/ExpectationApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/ExpectationApiTest.java @@ -15,6 +15,7 @@ import static java.util.Collections.emptyList; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -433,7 +434,8 @@ void getInjectExpectationsForSource() throws Exception { String response = mvc.perform( get(INJECTS_EXPECTATIONS_URI + "/assets/" + savedCollector.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -476,7 +478,8 @@ void getInjectPreventionExpectationsForSource() throws Exception { String response = mvc.perform( get(INJECTS_EXPECTATIONS_URI + "/prevention/" + savedCollector.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -515,7 +518,8 @@ void getInjectPreventionExpectationsForSource() throws Exception { response = mvc.perform( get(INJECTS_EXPECTATIONS_URI + "/prevention/" + savedCollector.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -560,7 +564,8 @@ void getInjectDetectionExpectationsForSource() throws Exception { String response = mvc.perform( get(INJECTS_EXPECTATIONS_URI + "/detection/" + savedCollector.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -599,7 +604,8 @@ void getInjectDetectionExpectationsForSource() throws Exception { response = mvc.perform( get(INJECTS_EXPECTATIONS_URI + "/detection/" + savedCollector.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -794,7 +800,8 @@ void bulkUpdateInjectExpectationWithTwoSuccess() throws Exception { put(INJECTS_EXPECTATIONS_URI + "/bulk") .content(asJsonString(inputs)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // -- ASSERT -- @@ -858,7 +865,8 @@ void getAvailableInjectExpectationsForInjects() throws Exception { get(INJECTS_EXPECTATIONS_URI + "/available?injectorContractId=" + mailInjectorContract.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -874,7 +882,8 @@ void getAvailableInjectExpectationsForInjects() throws Exception { get(INJECTS_EXPECTATIONS_URI + "/available?injectorContractId=" + challengeInjectorContract.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -891,7 +900,8 @@ void getAvailableInjectExpectationsForInjects() throws Exception { get(INJECTS_EXPECTATIONS_URI + "/available?injectorContractId=" + savedInjectorContract.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/MapperApiTest.java b/openaev-api/src/test/java/io/openaev/rest/MapperApiTest.java index dc5cad4e325..c4206c1f894 100644 --- a/openaev-api/src/test/java/io/openaev/rest/MapperApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/MapperApiTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.fasterxml.jackson.databind.ObjectMapper; @@ -96,7 +97,8 @@ void searchMappers() throws Exception { .perform( MockMvcRequestBuilders.post("/api/mappers/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(PaginationFixture.getDefault().textSearch("").build()))) + .content(asJsonString(PaginationFixture.getDefault().textSearch("").build())) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -119,7 +121,8 @@ void searchSpecificMapper() throws Exception { this.mvc .perform( MockMvcRequestBuilders.get("/api/mappers/" + importMapper.getId()) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -145,7 +148,8 @@ void createMapper() throws Exception { .perform( MockMvcRequestBuilders.post("/api/mappers/") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(importMapperInput))) + .content(asJsonString(importMapperInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -170,7 +174,8 @@ void duplicateMapper() throws Exception { .perform( MockMvcRequestBuilders.post("/api/mappers/" + importMapper.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(importMapper))) + .content(asJsonString(importMapper)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -191,7 +196,8 @@ void deleteSpecificMapper() throws Exception { .perform( MockMvcRequestBuilders.delete("/api/mappers/" + importMapper.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(PaginationFixture.getDefault().textSearch("").build()))) + .content(asJsonString(PaginationFixture.getDefault().textSearch("").build())) + .with(csrf())) .andExpect(status().is2xxSuccessful()); verify(importMapperRepository, times(1)).deleteById(any()); @@ -212,7 +218,8 @@ void updateSpecificMapper() throws Exception { .perform( MockMvcRequestBuilders.put("/api/mappers/" + importMapper.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(importMapperInput))) + .content(asJsonString(importMapperInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -237,7 +244,8 @@ void testStoreXls() throws Exception { // -- EXECUTE -- String response = this.mvc - .perform(MockMvcRequestBuilders.multipart("/api/mappers/store").file(xlsFile)) + .perform( + MockMvcRequestBuilders.multipart("/api/mappers/store").file(xlsFile).with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -271,7 +279,8 @@ void testTestingXls() throws Exception { MockMvcRequestBuilders.post( "/api/mappers/store/{importId}", UUID.randomUUID().toString()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(injectsImportInput))) + .content(asJsonString(injectsImportInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/PayloadApiSearchTest.java b/openaev-api/src/test/java/io/openaev/rest/PayloadApiSearchTest.java index 6b31b1d454d..e19ada3ca3d 100644 --- a/openaev-api/src/test/java/io/openaev/rest/PayloadApiSearchTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/PayloadApiSearchTest.java @@ -175,7 +175,8 @@ void given_filter_input_by_name_should_return_a_page_of_payloads_filter_by_name( mvc.perform( post(PAYLOAD_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -191,7 +192,8 @@ void given_filter_input_by_platforms_should_return_a_page_of_payloads_filter_by_ mvc.perform( post(PAYLOAD_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -207,7 +209,8 @@ void given_filter_input_by_source_should_return_a_page_of_payloads_filter_by_sou mvc.perform( post(PAYLOAD_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(3)); } @@ -224,7 +227,8 @@ void given_filter_input_by_source_should_return_a_page_of_payloads_filter_by_sou mvc.perform( post(PAYLOAD_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(3)); } diff --git a/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java b/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java index 4effd230dd6..5dbb7635a75 100644 --- a/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java @@ -100,7 +100,7 @@ void shouldFetchCveById() throws Exception { vulnerabilityComposer.forVulnerability(vulnerability).persist(); String response = - mvc.perform(get(VULNERABILITY_API + "/" + vulnerability.getId())) + mvc.perform(get(VULNERABILITY_API + "/" + vulnerability.getId()).with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java index c0e9ba0600b..baff4730807 100644 --- a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java @@ -227,7 +227,9 @@ void updateInjectForScenarioTest() throws Exception { @WithMockUser(isAdmin = true) void deleteInjectForScenarioTest() throws Exception { // -- EXECUTE 1 ASSERT -- - mvc.perform(delete(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects/" + SCENARIO_INJECT_ID)) + mvc.perform( + delete(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects/" + SCENARIO_INJECT_ID) + .with(csrf())) .andExpect(status().is2xxSuccessful()); assertFalse(injectRepository.existsById(SCENARIO_INJECT_ID)); @@ -279,7 +281,8 @@ void given_injectByTTPNumberMoreThan5_should_throwAnException() { post(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects/assistant") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON))); + .accept(MediaType.APPLICATION_JSON) + .with(csrf()))); // --ASSERT-- assertTrue( From 8606cb1d3607f720d3af9f628635bbbf907ba6e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Tue, 24 Feb 2026 23:42:05 +0100 Subject: [PATCH 05/20] [backend] fix(csrf): tests (#1785) --- .../java/io/openaev/rest/TeamApiTest.java | 31 ++-- .../java/io/openaev/rest/VariableApiTest.java | 19 ++- .../rest/asset_group/AssetGroupApiTest.java | 40 +++-- .../openaev/rest/inject/InjectImportTest.java | 4 +- .../rest/inject/InjectTargetSearchTest.java | 154 ++++++++++++------ .../InjectorContractApiTest.java | 131 ++++++++++----- .../NotificationRuleApiTest.java | 28 +++- .../openaev/rest/payload/PayloadApiTest.java | 118 +++++++++----- .../io/openaev/rest/role/RoleApiTest.java | 21 ++- .../rest/scenario/ScenarioApiSearchTest.java | 34 ++-- .../rest/scenario/ScenarioApiTest.java | 44 +++-- .../scenario/ScenarioInjectApiSearchTest.java | 19 ++- .../rest/scenario/ScenarioInjectApiTest.java | 15 +- .../scenario/ScenarioSimulationApiTest.java | 22 ++- .../rest/scenario/ScenarioTeamApiTest.java | 22 ++- .../rest/search/FullTextSearchTest.java | 16 +- .../openaev/rest/tag_rule/TagRuleApiTest.java | 38 +++-- 17 files changed, 510 insertions(+), 246 deletions(-) diff --git a/openaev-api/src/test/java/io/openaev/rest/TeamApiTest.java b/openaev-api/src/test/java/io/openaev/rest/TeamApiTest.java index 4881ab2316d..c56ff8cb425 100644 --- a/openaev-api/src/test/java/io/openaev/rest/TeamApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/TeamApiTest.java @@ -6,6 +6,7 @@ import static io.openaev.utils.fixtures.TeamFixture.*; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -63,7 +64,8 @@ void given_validTeamInput_should_createTeamSuccessfully() throws Exception { post(TEAM_URI) .content(asJsonString(teamInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -91,7 +93,8 @@ void given_existingTeamNameInput_should_throwAnException() throws Exception { post(TEAM_URI) .content(asJsonString(teamInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()) .andReturn() .getResponse() @@ -119,7 +122,8 @@ void given_validContextualTeamInput_should_createContextualTeamSuccessfully() th post(TEAM_URI) .content(asJsonString(teamInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -150,7 +154,8 @@ void given_existingContextualTeamNameInput_should_throwAnException() throws Exce post(TEAM_URI) .content(asJsonString(teamInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()) .andReturn() .getResponse() @@ -181,7 +186,8 @@ void given_validTeamIdAndInput_should_updateTeamSuccessfully() throws Exception put(TEAM_URI + "/" + team.getId()) .content(asJsonString(teamInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -210,7 +216,8 @@ void given_validTeamIdAndInput_should_upsertTeamSuccessfully() throws Exception post(TEAM_URI + "/upsert") .content(asJsonString(teamInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -235,7 +242,8 @@ void given_nonExistingTeamInput_should_upsertTeamSuccessfully() throws Exception post(TEAM_URI + "/upsert") .content(asJsonString(teamInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -269,7 +277,8 @@ void given_contextualTeamWithMultipleExercise_should_throwAnException() { post(TEAM_URI + "/upsert") .content(asJsonString(teamInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON))); + .accept(MediaType.APPLICATION_JSON) + .with(csrf()))); String expectedMessage = "Contextual team can only be associated to one exercise"; String actualMessage = exception.getMessage(); @@ -350,7 +359,8 @@ void optionsByNameTest( get(TEAM_URI + "/options") .queryParam("searchText", searchText) .queryParam("sourceId", simulationOrScenarioId ? exercise.getId() : null) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andReturn() .getResponse() .getContentAsString(); @@ -390,7 +400,8 @@ void optionsByIdTest(Integer numberOfTeamToProvide, Integer expectedNumberOfResu post(TEAM_URI + "/options") .content(asJsonString(teamIdsToSearch)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andReturn() .getResponse() .getContentAsString(); diff --git a/openaev-api/src/test/java/io/openaev/rest/VariableApiTest.java b/openaev-api/src/test/java/io/openaev/rest/VariableApiTest.java index 13c2d1bcb87..13518098d60 100644 --- a/openaev-api/src/test/java/io/openaev/rest/VariableApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/VariableApiTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -70,7 +71,8 @@ void createVariableForScenarioTest() throws Exception { post(SCENARIO_URI + "/" + SCENARIO_ID + "/variables") .content(asJsonString(variable)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()); // -- PREPARE -- @@ -85,7 +87,8 @@ void createVariableForScenarioTest() throws Exception { post(SCENARIO_URI + "/" + SCENARIO_ID + "/variables") .content(asJsonString(variable)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.variable_key").value(variableKey)) .andReturn() @@ -107,7 +110,8 @@ void retrieveVariableForScenarioTest() throws Exception { this.mvc .perform( get(SCENARIO_URI + "/" + SCENARIO_ID + "/variables") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -127,7 +131,8 @@ void updateVariableForScenarioTest() throws Exception { this.mvc .perform( get(SCENARIO_URI + "/" + SCENARIO_ID + "/variables") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -145,7 +150,8 @@ void updateVariableForScenarioTest() throws Exception { put(SCENARIO_URI + "/" + SCENARIO_ID + "/variables/" + VARIABLE_ID) .content(asJsonString(variable)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -163,7 +169,8 @@ void updateVariableForScenarioTest() throws Exception { void deleteVariableForScenarioTest() throws Exception { // -- EXECUTE 1 ASSERT -- this.mvc - .perform(delete(SCENARIO_URI + "/" + SCENARIO_ID + "/variables/" + VARIABLE_ID)) + .perform( + delete(SCENARIO_URI + "/" + SCENARIO_ID + "/variables/" + VARIABLE_ID).with(csrf())) .andExpect(status().is2xxSuccessful()); } } diff --git a/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiTest.java b/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiTest.java index 38b0478e6eb..72b030592c7 100644 --- a/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiTest.java @@ -7,6 +7,7 @@ import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -68,7 +69,8 @@ void given_validAssetGroupInput_should_createAndGetAssetGroupWithoutDynamicFilte post(ASSET_GROUP_URI) .content(asJsonString(assetGroupInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -88,7 +90,8 @@ void given_validAssetGroupInput_should_createAndGetAssetGroupWithoutDynamicFilte mvc.perform( get(ASSET_GROUP_URI + "/" + JsonPath.read(response, "$.asset_group_id")) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -128,7 +131,8 @@ void given_validAssetGroupInput_should_createAndGetAssetGroupWithDynamicFilterSu post(ASSET_GROUP_URI) .content(asJsonString(assetGroupInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -147,7 +151,8 @@ void given_validAssetGroupInput_should_createAndGetAssetGroupWithDynamicFilterSu mvc.perform( get(ASSET_GROUP_URI + "/" + JsonPath.read(response, "$.asset_group_id")) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -177,7 +182,8 @@ void should_createOneAssetGroupWithJavaAndOneWithSQLAndCompareThem() throws Exce post(ASSET_GROUP_URI) .content(asJsonString(assetGroupInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -216,7 +222,8 @@ void given_validAssetGroupInput_should_updateAssetGroupSuccessfully() throws Exc put(ASSET_GROUP_URI + "/" + assetGroup.getId()) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -242,10 +249,11 @@ void given_validAssetGroupInputForNonexistentAssetGroup_should_returnNotFound() ServletException.class, () -> mvc.perform( - put(ASSET_GROUP_URI + "/" + nonexistentAssetGroupId) - .content(asJsonString(input)) - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON))); + put(ASSET_GROUP_URI + "/" + nonexistentAssetGroupId) + .content(asJsonString(input)) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .with(csrf())); } @DisplayName("Given existing assetGroup, should delete assetGroup successfully") @@ -259,7 +267,8 @@ void given_existingAssetGroup_should_deleteAssetGroupSuccessfully() throws Excep mvc.perform( delete(ASSET_GROUP_URI + "/" + assetGroup.getId()) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // --ASSERT-- @@ -277,7 +286,8 @@ void given_notExistingAssetGroup_should_throwAnException() throws Exception { mvc.perform( delete(ASSET_GROUP_URI + "/" + nonexistentAssetGroupId) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()); } @@ -352,7 +362,8 @@ void optionsByNameTest( get(ASSET_GROUP_URI + "/options") .queryParam("searchText", searchText) .queryParam("sourceId", simulationOrScenarioId ? exercise.getId() : null) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andReturn() .getResponse() .getContentAsString(); @@ -392,7 +403,8 @@ void optionsByIdTest(Integer numberOfAssetGroupsToProvide, Integer expectedNumbe post(ASSET_GROUP_URI + "/options") .content(asJsonString(idsToSearch)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andReturn() .getResponse() .getContentAsString(); diff --git a/openaev-api/src/test/java/io/openaev/rest/inject/InjectImportTest.java b/openaev-api/src/test/java/io/openaev/rest/inject/InjectImportTest.java index 31b085076fd..41f9db4fd28 100644 --- a/openaev-api/src/test/java/io/openaev/rest/inject/InjectImportTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/inject/InjectImportTest.java @@ -9,6 +9,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -309,7 +310,8 @@ private ResultActions doImportStringInput(String uri, byte[] importZipData) thro mvc.perform( multipart(uri) .file(new MockMultipartFile("file", importZipData)) - .contentType(MediaType.MULTIPART_FORM_DATA)); + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())); clearEntityManager(); return ra; } diff --git a/openaev-api/src/test/java/io/openaev/rest/inject/InjectTargetSearchTest.java b/openaev-api/src/test/java/io/openaev/rest/inject/InjectTargetSearchTest.java index e046d2419df..a92546bead8 100644 --- a/openaev-api/src/test/java/io/openaev/rest/inject/InjectTargetSearchTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/inject/InjectTargetSearchTest.java @@ -3,6 +3,7 @@ import static io.openaev.rest.inject.InjectApi.INJECT_URI; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -117,7 +118,8 @@ public void whenInjectDoesNotExist_returnNotFound() throws Exception { mvc.perform( post(INJECT_URI + "/" + id + "/targets/" + TargetType.ASSETS_GROUPS + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(new SearchPaginationInput()))) + .content(mapper.writeValueAsString(new SearchPaginationInput())) + .with(csrf())) .andExpect(status().isNotFound()); } } @@ -138,7 +140,8 @@ public void whenTargetTypeDoesNotExist_returnBadRequest() throws Exception { + "THIS_TARGET_TYPE_DOES_NOT_EXIST" + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(new SearchPaginationInput()))) + .content(mapper.writeValueAsString(new SearchPaginationInput())) + .with(csrf())) .andExpect(status().isBadRequest()); } } @@ -154,7 +157,8 @@ public void withoutAuthorisation_returnNotFound() throws Exception { mvc.perform( post(INJECT_URI + "/" + id + "/targets/" + TargetType.ASSETS_GROUPS + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(new SearchPaginationInput()))) + .content(mapper.writeValueAsString(new SearchPaginationInput())) + .with(csrf())) .andExpect(status().isNotFound()); } } @@ -179,7 +183,8 @@ public void whenEndpointsAreFilters_returnAllPossibleTargets() throws Exception String response = mvc.perform( get(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/options") - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -224,7 +229,8 @@ public void whenEndpointsAreFilters_returnOnlyOptionsMatchingIds() throws Except mvc.perform( post(INJECT_URI + "/targets/" + targetType + "/options") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(ids))) + .content(mapper.writeValueAsString(ids)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -321,7 +327,8 @@ public void orFilterGroupCombinationShouldNotReturnAgentThatIsNotTargetOfInject( mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -446,7 +453,8 @@ public void whenAgentBelongsToDynamicAssetInGroup_thenTargetIsDynamicAssetInGrou mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -537,7 +545,8 @@ public void whenDynamicGroupsIntersect_thenReturnCommonAgentsOnce() throws Excep mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -627,7 +636,8 @@ public void whenNoAppliedAssetGroupFilter_returnPageOfAllTargetedAgents() throws mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -732,7 +742,8 @@ public void whenEndpointsAreExplicitlyTargeted_thenReturnOnlyAgentsFromEndpoints mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -812,7 +823,8 @@ public void whenEndpointsAreExplicitlyTargeted_thenReturnOnlyAgentsFromEndpoints mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -893,7 +905,8 @@ public void whenArePartOfAGroupAndGroupFilteredOut_thenExcludeAllAgentsFromEndpo mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -978,7 +991,8 @@ public void whenArePartOfAGroupAndGroupFilteredOut_thenExcludeAllAgentsFromEndpo mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1065,7 +1079,8 @@ public class WhenFilteringWithTags { mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1149,7 +1164,8 @@ public class WhenFilteringWithTags { mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1232,7 +1248,8 @@ public void whenEndpointsAreExplicitlyTargeted_thenReturnOnlyAgentsFromEndpoints mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1316,7 +1333,8 @@ public void whenEndpointsAreExplicitlyTargeted_thenReturnOnlyAgentsFromEndpoints mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1388,7 +1406,8 @@ public void whenEndpointsAreFilters_returnAllPossibleTargets() throws Exception String response = mvc.perform( get(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/options") - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1446,7 +1465,8 @@ public void whenEndpointsAreFilters_returnAllTargetsMatchingSearchText() throws mvc.perform( get(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/options") .queryParam("searchText", "search this") - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1506,7 +1526,8 @@ public void whenEndpointsAreFilters_returnOnlyOptionsMatchingIds() throws Except mvc.perform( post(INJECT_URI + "/targets/" + targetType + "/options") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(ids))) + .content(mapper.writeValueAsString(ids)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1585,7 +1606,8 @@ public void whenEndpointsAreExplicitlyTargeted_thenReturnOnlyEndpointsWithNoGrou mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1696,7 +1718,8 @@ public void whenEndpointIsDynamicAssetInGroup_thenTargetIsDynamicAssetInGroup() mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1771,7 +1794,8 @@ public void whenDynamicGroupsIntersect_thenReturnCommonEndpointsOnce() throws Ex mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1838,7 +1862,8 @@ public void whenNoAppliedAssetGroupFilter_returnPageOfAllTargetedEndpoints() mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1916,7 +1941,8 @@ public void whenEndpointsAreExplicitlyTargeted_thenReturnOnlyEndpointsWithNoGrou mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1980,7 +2006,8 @@ public void whenEndpointsAreExplicitlyTargeted_thenReturnOnlyEndpointsWithGroup( mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2044,7 +2071,8 @@ public void whenArePartOfAGroupAndGroupFilteredOut_thenExcludeAllEndpointsOfGrou mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2111,7 +2139,8 @@ public void whenArePartOfAGroupAndGroupSelectedAsFilter_thenIncludeOnlyEndpoints mvc.perform( post(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2174,7 +2203,8 @@ public void whenAssetGroupsAreTargets_returnAllPossibleTargets() throws Exceptio String response = mvc.perform( get(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/options") - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2228,7 +2258,8 @@ public void whenAssetGroupsAreTargets_returnAllPossibleTargetsMatchingSearchText get(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/options") // keep lower case for case-insensitive search .queryParam("searchText", "returnthis") - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2280,7 +2311,8 @@ public void whenAssetGroupsAreTargets_returnOnlyOptionsMatchingIds() throws Exce mvc.perform( post(INJECT_URI + "/targets/" + targetType + "/options") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(ids))) + .content(mapper.writeValueAsString(ids)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2316,7 +2348,8 @@ public void withNoAssetGroupTargets_returnNoItemsInPage() throws Exception { + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2349,7 +2382,8 @@ public void withSomeAssetGroupTargets_returnMatchingItemsInPage1() throws Except + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2397,7 +2431,8 @@ public void withSomeAssetGroupTargets_returnMatchingItemsInPage2() throws Except + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2471,7 +2506,8 @@ public void givenSpecificScores_expectationTypeResultsAreOfCorrectStatus() throw + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2526,7 +2562,8 @@ public void whenTeamsAreTargets_returnAllPossibleTargets() throws Exception { String response = mvc.perform( get(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/options") - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2575,7 +2612,8 @@ public void whenTeamsAreTargets_returnAllPossibleTargetsForExerciseAllTeams() + "/targets/" + targetType + "/options") - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2624,7 +2662,8 @@ public void whenTeamsAreTargets_returnAllPossibleTargetsForExerciseWithInjectWit + "/targets/" + targetType + "/options") - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2660,7 +2699,8 @@ public void whenTeamsAreTargets_returnAllPossibleTargetsMatchingSearchText() mvc.perform( get(INJECT_URI + "/" + inject.getId() + "/targets/" + targetType + "/options") .queryParam("searchText", "Other") - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2695,7 +2735,8 @@ public void whenTeamsAreTargets_returnOnlyOptionsMatchingIds() throws Exception mvc.perform( post(INJECT_URI + "/targets/" + targetType + "/options") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(ids))) + .content(mapper.writeValueAsString(ids)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2731,7 +2772,8 @@ public void withNoTeamTargets_returnNoItemsInPage() throws Exception { + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2764,7 +2806,8 @@ public void withSomeTeamTargets_returnMatchingItemsInPage1() throws Exception { + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2810,7 +2853,8 @@ public void withSomeTeamTargets_returnMatchingItemsInPage2() throws Exception { + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2868,7 +2912,8 @@ public void withSomeTeamsTargets_returnMatchingItemsForExercisesWithInjectAllTea + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2926,7 +2971,8 @@ public void givenSpecificScores_expectationTypeResultsAreOfCorrectStatus() throw + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -2975,7 +3021,8 @@ public void withNoPlayerTargets_returnNoItemsInPage() throws Exception { + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -3014,7 +3061,8 @@ public void withSomePlayersTargets_returnMatchingItemsInPage1() throws Exception + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -3069,7 +3117,8 @@ public void withSomePlayersTargets_returnMatchingItemsInPage2() throws Exception + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -3130,7 +3179,8 @@ public void withSomePlayersTargets_returnMatchingItemsForExercisesWithInjectAllT + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -3189,7 +3239,8 @@ public void withSomePlayersTargets_returnMatchingItemsForExercisesWithInjectWith + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -3253,7 +3304,8 @@ public void givenSpecificScores_expectationTypeResultsAreOfCorrectStatus() throw + targetType.name() + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(search))) + .content(mapper.writeValueAsString(search)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/injector_contract/InjectorContractApiTest.java b/openaev-api/src/test/java/io/openaev/rest/injector_contract/InjectorContractApiTest.java index 5bb07862fa6..9f5bcc4ff1c 100644 --- a/openaev-api/src/test/java/io/openaev/rest/injector_contract/InjectorContractApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/injector_contract/InjectorContractApiTest.java @@ -8,6 +8,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -106,7 +107,10 @@ class WithInternalId { @Test @DisplayName("When internal ID is empty, fetching by internal ID fails with NOT FOUND") void whenExternalIdIsNull_FetchingByExternalIdFailsWithBadRequest() throws Exception { - mvc.perform(get(INJECTOR_CONTRACT_URL + "//").contentType(MediaType.APPLICATION_JSON)) + mvc.perform( + get(INJECTOR_CONTRACT_URL + "//") + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -149,7 +153,8 @@ void updatingAttackPatternMappingsSucceeds() throws Exception { + injectorContractComposer.generatedItems.getFirst().getId() + "/mapping") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()); } @@ -167,7 +172,8 @@ void updatingAttackPatternMappingsWithNonExistingAttackPatternsFailWithNotFound( + injectorContractComposer.generatedItems.getFirst().getId() + "/mapping") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -194,7 +200,8 @@ void updatingVulnerabilitiesMappingsSucceeds() throws Exception { + injectorContractComposer.generatedItems.getFirst().getId() + "/mapping") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()); } @@ -212,7 +219,8 @@ void updatingVulnerabilitiesMappingsWithNonExistingVulnerabilitiesFailWithNotFou + injectorContractComposer.generatedItems.getFirst().getId() + "/mapping") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -225,7 +233,8 @@ void fetchByExternalIdSucceeds() throws Exception { get(INJECTOR_CONTRACT_URL + "/" + injectorContractComposer.generatedItems.getFirst().getId()) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -253,7 +262,8 @@ void deleteNonCustomContractFails() { .generatedItems .getFirst() .getId()) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andReturn()) .hasCauseInstanceOf(IllegalArgumentException.class) .hasMessageEndingWith( @@ -281,7 +291,8 @@ void deleteCustomContractSucceeds() throws Exception { mvc.perform( delete(INJECTOR_CONTRACT_URL + "/" + customContract.getExternalId()) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()); } } @@ -318,7 +329,8 @@ void updateContractSucceeds() throws Exception { + "/" + injectorContractComposer.generatedItems.getFirst().getId()) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -372,7 +384,8 @@ void updateContractWithExtVulnIdsSucceeds() throws Exception { + "/" + injectorContractComposer.generatedItems.getFirst().getId()) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -412,7 +425,8 @@ void createContractSucceeds() throws Exception { mvc.perform( post(INJECTOR_CONTRACT_URL) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -460,7 +474,8 @@ void withMissingAttackPatternsCreateContractFailsWithNOTFOUND() throws Exception mvc.perform( post(INJECTOR_CONTRACT_URL) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -482,7 +497,8 @@ void withMissingVulnerabilitiesCreateContractFailsWithNOTFOUND() throws Exceptio mvc.perform( post(INJECTOR_CONTRACT_URL) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -514,7 +530,8 @@ void withExistingAttackPatternsByInternalIdCreateContractSucceeds() throws Excep mvc.perform( post(INJECTOR_CONTRACT_URL) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -579,7 +596,8 @@ void withExistingAttackPatternsByExternalIdCreateContractSucceeds() throws Excep mvc.perform( post(INJECTOR_CONTRACT_URL) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -644,7 +662,8 @@ void withExistingVulnerabilitiesCreateContractSucceeds() throws Exception { mvc.perform( post(INJECTOR_CONTRACT_URL) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -713,7 +732,8 @@ void withExistingVulnerabilitiesByExternalIdCreateContractSucceeds() throws Exce mvc.perform( post(INJECTOR_CONTRACT_URL) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -754,7 +774,8 @@ void withExistingVulnerabilitiesByExternalIdCreateContractSucceeds() throws Exce void fetchByInternalIdFailsWithNotFound() throws Exception { mvc.perform( get(INJECTOR_CONTRACT_URL + "/" + injectorContractInternalId) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -776,7 +797,8 @@ void updatingAttackPatternMappingsFailsWithNotFound() throws Exception { mvc.perform( put(INJECTOR_CONTRACT_URL + "/" + injectorContractInternalId + "/mapping") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -785,7 +807,8 @@ void updatingAttackPatternMappingsFailsWithNotFound() throws Exception { void deleteContractFailsWithNotFound() throws Exception { mvc.perform( delete(INJECTOR_CONTRACT_URL + "/" + injectorContractInternalId) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -804,7 +827,8 @@ void updateContractFailsWithNotFound() throws Exception { mvc.perform( put(INJECTOR_CONTRACT_URL + "/" + injectorContractInternalId) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isNotFound()); } } @@ -819,7 +843,10 @@ class WithExternalId { @Test @DisplayName("When external ID is empty, fetching by External ID fails with NOT FOUND") void whenExternalIdIsNull_FetchingByExternalIdFailsWithBadRequest() throws Exception { - mvc.perform(get(INJECTOR_CONTRACT_URL + "//").contentType(MediaType.APPLICATION_JSON)) + mvc.perform( + get(INJECTOR_CONTRACT_URL + "//") + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -871,7 +898,8 @@ void updatingAttackPatternMappingsSucceeds() throws Exception { mvc.perform( put(INJECTOR_CONTRACT_URL + "/" + externalId + "/mapping") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()); } @@ -886,7 +914,8 @@ void updatingAttackPatternMappingsWithNonExistingAttackPatternsFailWithNotFound( mvc.perform( put(INJECTOR_CONTRACT_URL + "/" + externalId + "/mapping") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -910,7 +939,8 @@ void updatingVulnerabilitiesMappingsSucceeds() throws Exception { mvc.perform( put(INJECTOR_CONTRACT_URL + "/" + externalId + "/mapping") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()); } @@ -925,7 +955,8 @@ void updatingVulnerabilitiesMappingsWithNonExistingVulnerabilitiesFailWithNotFou mvc.perform( put(INJECTOR_CONTRACT_URL + "/" + externalId + "/mapping") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -936,7 +967,8 @@ void fetchByExternalIdSucceeds() throws Exception { String body = mvc.perform( get(INJECTOR_CONTRACT_URL + "/" + externalId) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -958,7 +990,8 @@ void deleteNonCustomContractFails() { () -> mvc.perform( delete(INJECTOR_CONTRACT_URL + "/" + externalId) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andReturn()) .hasCauseInstanceOf(IllegalArgumentException.class) .hasMessageEndingWith( @@ -986,7 +1019,8 @@ void deleteCustomContractSucceeds() throws Exception { mvc.perform( delete(INJECTOR_CONTRACT_URL + "/" + customContract.getExternalId()) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()); } } @@ -1021,7 +1055,8 @@ void updateContractSucceeds() throws Exception { mvc.perform( put(INJECTOR_CONTRACT_URL + "/" + externalId) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1060,7 +1095,8 @@ void createContractSucceedsFromInjectorPayloadType() throws Exception { mvc.perform( post(INJECTOR_CONTRACT_URL) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1109,7 +1145,8 @@ void createContractSucceeds() throws Exception { mvc.perform( post(INJECTOR_CONTRACT_URL) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1149,7 +1186,8 @@ void createContractSucceeds() throws Exception { void fetchByExternalIdFailsWithNotFound() throws Exception { mvc.perform( get(INJECTOR_CONTRACT_URL + "/" + externalId) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -1171,7 +1209,8 @@ void updatingAttackPatternMappingsFailsWithNotFound() throws Exception { mvc.perform( put(INJECTOR_CONTRACT_URL + "/" + externalId + "/mapping") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -1180,7 +1219,8 @@ void updatingAttackPatternMappingsFailsWithNotFound() throws Exception { void deleteContractFailsWithNotFound() throws Exception { mvc.perform( delete(INJECTOR_CONTRACT_URL + "/" + externalId) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -1199,7 +1239,8 @@ void updateContractFailsWithNotFound() throws Exception { mvc.perform( put(INJECTOR_CONTRACT_URL + "/" + externalId) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isNotFound()); } } @@ -1238,7 +1279,8 @@ void WithClassicSearchPaginationInput() throws Exception { mvc.perform( post(INJECTOR_CONTRACT_URL + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1270,7 +1312,8 @@ void WithSearchPaginationWithSerialisationOptionsInput() throws Exception { mvc.perform( post(INJECTOR_CONTRACT_URL + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1440,7 +1483,8 @@ void testGetInjectContracts( mvc.perform( get(INJECTOR_CONTRACT_URL) .with(authentication(auth)) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andDo(print()) .andExpect(status().is(HttpStatus.SC_OK)); @@ -1484,7 +1528,8 @@ void testSearchInjectorContracts( post(INJECTOR_CONTRACT_URL + "/search") .with(authentication(auth)) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is(HttpStatus.SC_OK)); // Verify pagination response @@ -1525,7 +1570,8 @@ void testSearchInjectorContractsWithFullDetails( post(INJECTOR_CONTRACT_URL + "/search") .with(authentication(auth)) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is(HttpStatus.SC_OK)); // Verify pagination response with full details @@ -1590,7 +1636,8 @@ void getDomainCountsReturnAggregation() throws Exception { mvc.perform( post(INJECTOR_CONTRACT_URL + "/domain-counts") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/notification_rule/NotificationRuleApiTest.java b/openaev-api/src/test/java/io/openaev/rest/notification_rule/NotificationRuleApiTest.java index b13aad2953a..e97364e5b01 100644 --- a/openaev-api/src/test/java/io/openaev/rest/notification_rule/NotificationRuleApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/notification_rule/NotificationRuleApiTest.java @@ -3,6 +3,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -73,7 +74,8 @@ void createNotificationRule() throws Exception { post(NOTIFICATION_RULE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -103,7 +105,8 @@ void createNotificationRule_unexisting_scenario_id() throws Exception { post(NOTIFICATION_RULE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()); } @@ -122,7 +125,8 @@ void updateNotificationRule() throws Exception { put(NOTIFICATION_RULE_URI + "/" + notificationRule.getId()) .content(asJsonString(updatedInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -142,7 +146,8 @@ void updateNotificationRule_WITH_unexisting_id() throws Exception { put(NOTIFICATION_RULE_URI + "/randomid") .content(asJsonString(updatedInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()) .andReturn() .getResponse() @@ -158,7 +163,8 @@ void deleteNotificationRule() throws Exception { mvc.perform( delete(NOTIFICATION_RULE_URI + "/" + uuid) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -173,7 +179,8 @@ void deleteNotificationRule_WITH_unexisting_id() throws Exception { mvc.perform( delete(NOTIFICATION_RULE_URI + "/radomid") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()) .andReturn() .getResponse() @@ -190,7 +197,8 @@ void findNotificationRule() throws Exception { String response = mvc.perform( get(NOTIFICATION_RULE_URI + "/" + notificationRule.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -221,7 +229,8 @@ void findNotificationRuleByResource() throws Exception { String response = mvc.perform( get(NOTIFICATION_RULE_URI + "/resource/" + notificationRule.getResourceId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -260,7 +269,8 @@ void searchTagRule() throws Exception { post(NOTIFICATION_RULE_URI + "/search") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/payload/PayloadApiTest.java b/openaev-api/src/test/java/io/openaev/rest/payload/PayloadApiTest.java index b4ccc3533aa..7516120e6a1 100644 --- a/openaev-api/src/test/java/io/openaev/rest/payload/PayloadApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/payload/PayloadApiTest.java @@ -8,6 +8,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -99,7 +100,8 @@ void createExecutablePayload() throws Exception { mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("My Executable Payload")) .andExpect(jsonPath("$.payload_description").value("Executable description")) @@ -123,7 +125,8 @@ void createPayloadWithNullArch() throws Exception { mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isBadRequest()); } @@ -141,7 +144,8 @@ void createExecutablePayloadWithoutArch() throws Exception { mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -164,7 +168,8 @@ void given_payload_create_input_with_output_parsers_should_return_payload_with_o mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("Command line payload")) .andExpect( @@ -198,7 +203,8 @@ void given_payload_create_input_with_output_parsers_should_return_payload_with_o mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("Command line payload")) .andExpect(jsonPath("$.payload_detection_remediations.length()").value(3)); @@ -220,7 +226,8 @@ void given_payload_create_input_with_output_parsers_should_return_payload_with_o mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -239,7 +246,8 @@ void given_payload_create_input_with_output_parsers_should_return_payload_with_o mvc.perform( put(PAYLOAD_URI + "/" + payloadId) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(updateInput))) + .content(asJsonString(updateInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_detection_remediations.length()").value(3)) .andExpect( @@ -268,7 +276,8 @@ void given_targetedAssetArgument_should_create_payload_with_targeted_asset() thr mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("Command line payload")) // .andExpect(jsonPath("$.payload_arguments]").value("targeted-asset")) @@ -324,7 +333,8 @@ void updateExecutablePayload() throws Exception { mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("My Executable Payload")) .andExpect(jsonPath("$.payload_platforms.[0]").value("Linux")) @@ -344,7 +354,8 @@ void updateExecutablePayload() throws Exception { mvc.perform( put(PAYLOAD_URI + "/" + payloadId) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(updateInput))) + .content(asJsonString(updateInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("My Updated Executable Payload")) .andExpect(jsonPath("$.payload_platforms.[0]").value("MacOS")) @@ -366,7 +377,8 @@ void updateExecutablePayloadWithoutArch() throws Exception { mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -382,7 +394,8 @@ void updateExecutablePayloadWithoutArch() throws Exception { mvc.perform( put(PAYLOAD_URI + "/" + payloadId) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(updateInput))) + .content(asJsonString(updateInput)) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -404,7 +417,8 @@ void updatePayloadNoExecutableWithoutArch() throws Exception { mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -419,7 +433,8 @@ void updatePayloadNoExecutableWithoutArch() throws Exception { mvc.perform( put(PAYLOAD_URI + "/" + payloadId) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(updateInput))) + .content(asJsonString(updateInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("Updated Command line payload")) .andExpect(jsonPath("$.payload_platforms.[0]").value("MacOS")) @@ -443,7 +458,8 @@ void updatePayloadNoExecutableWithoutArch() throws Exception { mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -458,7 +474,8 @@ void updatePayloadNoExecutableWithoutArch() throws Exception { mvc.perform( put(PAYLOAD_URI + "/" + payloadId) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(updateInput))) + .content(asJsonString(updateInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("Updated Command line payload")) .andExpect( @@ -493,7 +510,8 @@ void updatePayloadNoExecutableWithoutArch() throws Exception { mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_detection_remediations.length()").value(0)) .andReturn() @@ -509,7 +527,8 @@ void updatePayloadNoExecutableWithoutArch() throws Exception { mvc.perform( put(PAYLOAD_URI + "/" + payloadId) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(updateInput))) + .content(asJsonString(updateInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_detection_remediations.length()").value(3)); ; @@ -532,7 +551,8 @@ void upsertCommandPayloadToValidateArchitecture() throws Exception { mvc.perform( post(PAYLOAD_URI + "/upsert") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(upsertInput))) + .content(asJsonString(upsertInput)) + .with(csrf())) .andExpect(status().isOk()) .andExpect( jsonPath("$.payload_execution_arch") @@ -543,7 +563,8 @@ void upsertCommandPayloadToValidateArchitecture() throws Exception { mvc.perform( post(PAYLOAD_URI + "/upsert") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(upsertInput))) + .content(asJsonString(upsertInput)) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -565,7 +586,10 @@ void upsertCommandPayloadToValidateArchitecture() throws Exception { List.of(domain.getId())); mvc.perform( - post(PAYLOAD_URI).contentType(MediaType.APPLICATION_JSON).content(asJsonString(input))) + post(PAYLOAD_URI) + .contentType(MediaType.APPLICATION_JSON) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().is2xxSuccessful()); PayloadUpsertInput upsertInput = @@ -575,7 +599,8 @@ void upsertCommandPayloadToValidateArchitecture() throws Exception { mvc.perform( post(PAYLOAD_URI + "/upsert") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(upsertInput))) + .content(asJsonString(upsertInput)) + .with(csrf())) .andExpect(status().isOk()) .andExpect( jsonPath("$.payload_output_parsers[0].output_parser_mode") @@ -614,7 +639,10 @@ void upsertCommandPayloadToValidateArchitecture() throws Exception { PayloadInputFixture.createDefaultPayloadCreateInputForCommandLine(List.of(domain.getId())); mvc.perform( - post(PAYLOAD_URI).contentType(MediaType.APPLICATION_JSON).content(asJsonString(input))) + post(PAYLOAD_URI) + .contentType(MediaType.APPLICATION_JSON) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_detection_remediations.length()").value(0)); @@ -626,7 +654,8 @@ void upsertCommandPayloadToValidateArchitecture() throws Exception { mvc.perform( post(PAYLOAD_URI + "/upsert") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(upsertInput))) + .content(asJsonString(upsertInput)) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.payload_detection_remediations.length()").value(3)); } @@ -648,7 +677,8 @@ void createCommandLinePayloadWithBothSetExecutorAndContent() throws Exception { mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().isOk()); } @@ -668,7 +698,8 @@ void createCommandLinePayloadWithBothNullCleanupExecutorAndCommand() throws Exce mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().isOk()); } @@ -688,7 +719,8 @@ void createCommandLinePayloadWithBothSetCleanupExecutorAndCommand() throws Excep mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().isOk()); } @@ -708,7 +740,8 @@ void createCommandLinePayloadWithOnlySetCleanupExecutorAndNullCommand() throws E mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().isConflict()); } @@ -728,7 +761,8 @@ void createCommandLinePayloadWithOnlySetCommandAndNullExecutor() throws Exceptio mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().isConflict()); } @@ -749,7 +783,8 @@ void updateCommandLinePayloadWithOnlySetCommandAndNullExecutor() throws Exceptio mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -769,7 +804,8 @@ void updateCommandLinePayloadWithOnlySetCommandAndNullExecutor() throws Exceptio mvc.perform( put(PAYLOAD_URI + "/" + payloadId) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(updateInput))) + .content(asJsonString(updateInput)) + .with(csrf())) .andExpect(status().isConflict()); } @@ -790,7 +826,8 @@ void duplicateExecutablePayload() throws Exception { mvc.perform( post(PAYLOAD_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(createInput))) + .content(asJsonString(createInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("My Executable Payload")) .andExpect(jsonPath("$.payload_platforms.[0]").value("Linux")) @@ -805,7 +842,7 @@ void duplicateExecutablePayload() throws Exception { var payloadId = JsonPath.read(createdPayload, "$.payload_id"); - mvc.perform(post(PAYLOAD_URI + "/" + payloadId + "/duplicate")) + mvc.perform(post(PAYLOAD_URI + "/" + payloadId + "/duplicate").with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("My Executable Payload (duplicate)")) .andExpect(jsonPath("$.payload_platforms.[0]").value("Linux")) @@ -833,7 +870,7 @@ void processDeprecatedPayloads() throws Exception { "application/json", objectMapper.writeValueAsString(collectorCreateInput).getBytes()); - mvc.perform(multipart("/api/collectors").file(inputMultipart)) + mvc.perform(multipart("/api/collectors").file(inputMultipart).with(csrf())) .andExpect(status().is2xxSuccessful()); Domain domain = domainComposer.forDomain(DomainFixture.getRandomDomain()).persist().get(); @@ -853,7 +890,8 @@ void processDeprecatedPayloads() throws Exception { mvc.perform( post(PAYLOAD_URI + "/upsert") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(payloadUpsertInput1))) + .content(asJsonString(payloadUpsertInput1)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -864,7 +902,8 @@ void processDeprecatedPayloads() throws Exception { mvc.perform( post(PAYLOAD_URI + "/upsert") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(payloadUpsertInput2))) + .content(asJsonString(payloadUpsertInput2)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -877,16 +916,17 @@ void processDeprecatedPayloads() throws Exception { mvc.perform( post(PAYLOAD_URI + "/deprecate") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(payloadsDeprecateInput))) + .content(asJsonString(payloadsDeprecateInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()); - mvc.perform(get(PAYLOAD_URI + "/" + payloadId1)) + mvc.perform(get(PAYLOAD_URI + "/" + payloadId1).with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("My Command Payload")) .andExpect(jsonPath("$.payload_collector").value(collectorId)) .andExpect(jsonPath("$.payload_status").value("DEPRECATED")); - mvc.perform(get(PAYLOAD_URI + "/" + payloadId2)) + mvc.perform(get(PAYLOAD_URI + "/" + payloadId2).with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.payload_name").value("Command Payload 2")) .andExpect(jsonPath("$.payload_collector").value(collectorId)) diff --git a/openaev-api/src/test/java/io/openaev/rest/role/RoleApiTest.java b/openaev-api/src/test/java/io/openaev/rest/role/RoleApiTest.java index 40dec3f2303..1e39d138fc2 100644 --- a/openaev-api/src/test/java/io/openaev/rest/role/RoleApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/role/RoleApiTest.java @@ -125,7 +125,8 @@ void test_updateRole() throws Exception { put(ROLE_URI + "/" + savedRole.getId()) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -147,7 +148,10 @@ void test_updateRole() throws Exception { void test_deleteRole() throws Exception { Role savedRole = roleRepository.save(RoleFixture.getRole()); - mvc.perform(delete(ROLE_URI + "/" + savedRole.getId()).accept(MediaType.APPLICATION_JSON)) + mvc.perform( + delete(ROLE_URI + "/" + savedRole.getId()) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -172,7 +176,8 @@ void test_searchRole() throws Exception { post(ROLE_URI + "/search") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -197,7 +202,8 @@ void test_getAllRoles() throws Exception { mvc.perform( get(ROLE_URI) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -224,7 +230,8 @@ void test_updateRole_WITH_nonexistent_id() throws Exception { put(ROLE_URI + "/randomid") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -232,7 +239,7 @@ void test_updateRole_WITH_nonexistent_id() throws Exception { @WithMockUser(isAdmin = true) void test_deleteRole_WITH_nonexistent_id() throws Exception { - mvc.perform(delete(ROLE_URI + "/randomid").accept(MediaType.APPLICATION_JSON)) + mvc.perform(delete(ROLE_URI + "/randomid").accept(MediaType.APPLICATION_JSON).with(csrf())) .andExpect(status().isNotFound()); } @@ -240,7 +247,7 @@ void test_deleteRole_WITH_nonexistent_id() throws Exception { @WithMockUser(isAdmin = true) void test_findRole_WITH_nonexistent_id() throws Exception { - mvc.perform(get(ROLE_URI + "/randomid").accept(MediaType.APPLICATION_JSON)) + mvc.perform(get(ROLE_URI + "/randomid").accept(MediaType.APPLICATION_JSON).with(csrf())) .andExpect(status().isNotFound()); } } diff --git a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioApiSearchTest.java b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioApiSearchTest.java index f56bc98c4d7..6286891a53b 100644 --- a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioApiSearchTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioApiSearchTest.java @@ -7,6 +7,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static java.lang.String.valueOf; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -76,7 +77,8 @@ void given_working_search_input_should_return_a_page_of_scenarios() throws Excep mvc.perform( post(SCENARIO_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -90,7 +92,8 @@ void given_not_working_search_input_should_return_a_page_of_scenarios() throws E mvc.perform( post(SCENARIO_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(0)); } @@ -112,7 +115,8 @@ void given_sorting_input_by_name_should_return_a_page_of_scenarios_sort_by_name( mvc.perform( post(SCENARIO_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[0].scenario_name").value("Crisis scenario")) .andExpect(jsonPath("$.content.[1].scenario_name").value("Incident response scenario")); @@ -135,7 +139,8 @@ void given_sorting_input_by_category_should_return_a_page_of_scenarios_sort_by_c mvc.perform( post(SCENARIO_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[0].scenario_name").value("Incident response scenario")) .andExpect(jsonPath("$.content.[1].scenario_name").value("Crisis scenario")); @@ -156,7 +161,8 @@ void given_filter_input_by_name_should_return_a_page_of_scenarios_filter_by_name mvc.perform( post(SCENARIO_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -172,7 +178,8 @@ void given_filter_input_by_category_should_return_a_page_of_scenarios_filter_by_ mvc.perform( post(SCENARIO_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -188,7 +195,8 @@ void given_filter_input_by_severity_should_return_a_page_of_scenarios_filter_by_ mvc.perform( post(SCENARIO_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -202,7 +210,8 @@ void given_list_of_ids_select_scenarios() throws Exception { mvc.perform( post(SCENARIO_URI + "/search-by-id") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(getScenariosInput))) + .content(asJsonString(getScenariosInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$").isArray()) .andExpect(jsonPath("$.length()").value(2)); @@ -218,7 +227,8 @@ void given_list_of_ids_select_scenarios_with_capabilities() throws Exception { mvc.perform( post(SCENARIO_URI + "/search-by-id") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(getScenariosInput))) + .content(asJsonString(getScenariosInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$").isArray()) .andExpect(jsonPath("$.length()").value(2)); @@ -234,7 +244,8 @@ void given_list_of_ids_select_scenarios_without_capabilities_no_grants() throws mvc.perform( post(SCENARIO_URI + "/search-by-id") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(getScenariosInput))) + .content(asJsonString(getScenariosInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$").isArray()) .andExpect(jsonPath("$.length()").value(0)); @@ -277,7 +288,8 @@ void given_list_of_ids_select_scenarios_without_capabilities_with_grants() throw mvc.perform( post(SCENARIO_URI + "/search-by-id") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(getScenariosInput))) + .content(asJsonString(getScenariosInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$").isArray()) .andExpect(jsonPath("$.length()").value(1)); diff --git a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioApiTest.java b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioApiTest.java index 112f5c5cd06..3456b90e27a 100644 --- a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioApiTest.java @@ -5,6 +5,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -83,7 +84,8 @@ void createScenarioTest() throws Exception { post(SCENARIO_URI) .content(asJsonString(scenarioInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()); // -- PREPARE -- @@ -99,7 +101,8 @@ void createScenarioTest() throws Exception { post(SCENARIO_URI) .content(asJsonString(scenarioInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.scenario_name").value(name)) .andReturn() @@ -145,7 +148,8 @@ void given_scenario_creation_should_set_default_custom_dashboard() throws Except post(SCENARIO_URI) .content(asJsonString(scenarioInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.scenario_name").value(name)) .andReturn() @@ -168,7 +172,7 @@ void retrieveScenariosTest() throws Exception { // -- EXECUTE -- String response = this.mvc - .perform(get(SCENARIO_URI).accept(MediaType.APPLICATION_JSON)) + .perform(get(SCENARIO_URI).accept(MediaType.APPLICATION_JSON).with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -191,7 +195,9 @@ void retrieveScenarioTest() throws Exception { String response = this.mvc .perform( - get(SCENARIO_URI + "/" + testScenario.getId()).accept(MediaType.APPLICATION_JSON)) + get(SCENARIO_URI + "/" + testScenario.getId()) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -207,7 +213,8 @@ void retrieveScenarioTest() throws Exception { void failsafeNonExistScenarioId() throws Exception { // -- EXECUTE -- this.mvc - .perform(get(SCENARIO_URI + "/DOESNOTEXIST").accept(MediaType.APPLICATION_JSON)) + .perform( + get(SCENARIO_URI + "/DOESNOTEXIST").accept(MediaType.APPLICATION_JSON).with(csrf())) .andExpect(status().isNotFound()); } @@ -232,7 +239,8 @@ void updateScenarioTest() throws Exception { put(SCENARIO_URI + "/" + testScenario.getId()) .content(asJsonString(scenarioInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -253,7 +261,7 @@ void deleteScenarioTest() throws Exception { // -- EXECUTE 1 ASSERT -- this.mvc - .perform(delete(SCENARIO_URI + "/" + testScenario.getId())) + .perform(delete(SCENARIO_URI + "/" + testScenario.getId()).with(csrf())) .andExpect(status().is2xxSuccessful()); } @@ -284,7 +292,8 @@ void checkIfRuleAppliesTest_WHEN_rule_found() throws Exception { post(SCENARIO_URI + "/" + scenario.getId() + "/check-rules") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -314,7 +323,8 @@ void checkIfRuleAppliesTest_WHEN_no_rule_found() throws Exception { post(SCENARIO_URI + "/" + scenario.getId() + "/check-rules") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -356,7 +366,7 @@ private Scenario getScenario(@Nullable Scenario scenario, @Nullable Executor exe void given_crowdstrikeAsset_should_not_startScenario() throws Exception { Scenario scenario = getScenario(null, executorFixture.getCrowdstrikeExecutor()); - mvc.perform(post(SCENARIO_URI + "/" + scenario.getId() + "/exercise/running")) + mvc.perform(post(SCENARIO_URI + "/" + scenario.getId() + "/exercise/running").with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -372,7 +382,8 @@ void given_taniumAsset_should_not_scheduleScenario() throws Exception { put(SCENARIO_URI + "/" + scenario.getId() + "/recurrence") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -388,7 +399,8 @@ void given_sentineloneAsset_should_not_scheduleScenario() throws Exception { put(SCENARIO_URI + "/" + scenario.getId() + "/recurrence") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -436,7 +448,8 @@ void given_crowdstrikeInsdeDynamicGroup_should_not_beAddedToScheduledExercise() + scenario.getInjects().getFirst().getId()) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -471,7 +484,8 @@ void replacingTeamsShouldEnableNewTeamUsers() throws Exception { put(SCENARIO_URI + "/" + scenarioSaved.getId() + "/teams/replace") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(input)) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()); // -- ASSERT -- diff --git a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiSearchTest.java b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiSearchTest.java index 988ae5a64f5..ee7ea4d3953 100644 --- a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiSearchTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiSearchTest.java @@ -6,6 +6,7 @@ import static io.openaev.utils.fixtures.InjectFixture.getInjectForEmailContract; import static io.openaev.utils.fixtures.ScenarioFixture.createDefaultCrisisScenario; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -89,7 +90,8 @@ void given_working_search_input_should_return_a_page_of_injects() throws Excepti mvc.perform( post(SCENARIO_URI + "/" + SCENARIO_ID + "/injects/simple") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -103,7 +105,8 @@ void given_not_working_search_input_should_return_a_page_of_injects() throws Exc mvc.perform( post(SCENARIO_URI + "/" + SCENARIO_ID + "/injects/simple") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(0)); } @@ -125,7 +128,8 @@ void given_sorting_input_by_name_should_return_a_page_of_injects_sort_by_name() mvc.perform( post(SCENARIO_URI + "/" + SCENARIO_ID + "/injects/simple") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[0].inject_title").value("Inject default email")) .andExpect(jsonPath("$.content.[1].inject_title").value("Inject global email")); @@ -148,7 +152,8 @@ void given_sorting_input_by_updated_at_should_return_a_page_of_injects_sort_by_u mvc.perform( post(SCENARIO_URI + "/" + SCENARIO_ID + "/injects/simple") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[0].inject_title").value("Inject global email")) .andExpect(jsonPath("$.content.[1].inject_title").value("Inject default email")); @@ -169,7 +174,8 @@ void given_filter_input_by_name_should_return_a_page_of_injects_filter_by_name() mvc.perform( post(SCENARIO_URI + "/" + SCENARIO_ID + "/injects/simple") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(2)); } @@ -186,7 +192,8 @@ void given_filter_input_by_name_should_return_a_page_of_injects_filter_by_name() mvc.perform( post(SCENARIO_URI + "/" + SCENARIO_ID + "/injects/simple") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(2)); } diff --git a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java index baff4730807..1b5a1ca8889 100644 --- a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectApiTest.java @@ -317,7 +317,8 @@ void given_injectByTTPNumberMoreThan5_should_throwAnException() { post(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects/assistant") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -361,7 +362,8 @@ void given_InjectorContractMatchingAllWindows_should_createOneInject() throws Ex post(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects/assistant") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -406,7 +408,8 @@ void given_TwoInjectorContractWindows_should_createTwoInjects() throws Exception post(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects/assistant") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -438,7 +441,8 @@ void given_NoInjectorContractMatching_should_createManualInject() throws Excepti post(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects/assistant") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -488,7 +492,8 @@ void given_TwoInjectByTTPNumber_should_createTwoInjects() throws Exception { post(SCENARIO_URI + "/" + SCENARIO.getId() + "/injects/assistant") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioSimulationApiTest.java b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioSimulationApiTest.java index 735d3276ab0..0ab25afa718 100644 --- a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioSimulationApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioSimulationApiTest.java @@ -4,6 +4,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -89,7 +90,8 @@ void given_scenarioId_should_return_all_exercises_of_scenario() throws Exception mvc.perform( post(SCENARIO_URI + "/" + scenario.getId() + "/exercises/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(2)) .andReturn() @@ -117,7 +119,8 @@ void given_scenarioId_and_tag_should_return_filtered_exercises_of_scenario() mvc.perform( post(SCENARIO_URI + "/" + scenario.getId() + "/exercises/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)) .andExpect(jsonPath("$.content[0].exercise_id").value(exercise2FromScenario.getId())); @@ -126,7 +129,8 @@ void given_scenarioId_and_tag_should_return_filtered_exercises_of_scenario() mvc.perform( post(SCENARIO_URI + "/" + scenario.getId() + "/exercises/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(0)); } @@ -154,7 +158,8 @@ void given_sorting_input_by_updateDate_should_return_a_page_of_exercises_sort_by mvc.perform( post(SCENARIO_URI + "/" + scenario.getId() + "/exercises/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(2)) .andExpect(jsonPath("$.content[0].exercise_id").value(exercise2FromScenario.getId())) @@ -197,7 +202,8 @@ void given_sorting_input_by_updateDate_should_return_a_page_of_exercises_sort_by mvc.perform( post(SCENARIO_URI + "/" + scenario.getId() + "/exercises/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(3)) .andExpect(jsonPath("$.content[0].exercise_id").value(exercise2FromScenario.getId())) @@ -217,7 +223,8 @@ void given_working_search_input_should_return_a_page_of_exercises() throws Excep mvc.perform( post(SCENARIO_URI + "/" + scenario.getId() + "/exercises/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)) .andExpect(jsonPath("$.content[0].exercise_id").value(exercise1FromScenario.getId())); @@ -233,7 +240,8 @@ void given_notworking_search_input_should_notreturn_a_page_of_exercises() throws mvc.perform( post(SCENARIO_URI + "/" + scenario.getId() + "/exercises/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(0)); } diff --git a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java index 366808c2a97..c432d418cfd 100644 --- a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java @@ -9,6 +9,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -81,7 +82,8 @@ void given_validScenarioAndTeamInput_should_replaceTeamToScenarioSuccessfully() put(SCENARIO_URI + "/" + scenarioCreated.getId() + "/teams/replace") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -130,7 +132,8 @@ void given_validScenarioWithTeams_should_retrieveTeamsSuccessfully() throws Exce this.mvc .perform( get(SCENARIO_URI + "/" + scenarioCreated.getId() + "/teams") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -171,7 +174,8 @@ void given_validScenarioAndTeam_should_addPlayerToTeamSuccessfully() throws Exce + "/players/add") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -223,7 +227,8 @@ void given_validScenarioAndTeamWithPlayer_should_removePlayerFromTeamSuccessfull + "/players/remove") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -258,7 +263,8 @@ void given_validScenarioWithTeam_should_removeTeamFromScenarioSuccessfully() thr put(SCENARIO_URI + "/" + scenarioCreated.getId() + "/teams/remove") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -299,7 +305,8 @@ void givenContextualOnlyFalse_whenSearchingTeams_shouldReturnGlobalAndScenarioTe + scenarioCreated.getId() + "/teams/search?contextualOnly=false") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.size()").value(2)) .andExpect( @@ -343,7 +350,8 @@ void givenContextualOnlyTrue_whenSearchingTeams_shouldReturnOnlyScenarioTeams() + scenarioCreated.getId() + "/teams/search?contextualOnly=true") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.size()").value(2)) .andExpect( diff --git a/openaev-api/src/test/java/io/openaev/rest/search/FullTextSearchTest.java b/openaev-api/src/test/java/io/openaev/rest/search/FullTextSearchTest.java index ad011deebbb..db5771150fa 100644 --- a/openaev-api/src/test/java/io/openaev/rest/search/FullTextSearchTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/search/FullTextSearchTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -110,7 +111,8 @@ void given_user_is_admin_search_input_should_return_count_for_all_scenarios( mvc.perform( post(GLOBAL_SEARCH_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(term))) + .content(asJsonString(term)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$['" + Scenario.class.getName() + "'].count").value(expectedCount)); } @@ -148,7 +150,8 @@ void given_user_is_admin_search_input_should_return_all_scenarios( mvc.perform( post(GLOBAL_SEARCH_URI + "/" + Scenario.class.getName()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.size()").value(expectedCount)) .andExpect(jsonPath("$.content[*].id", containsInAnyOrder(expectedIds.toArray()))); @@ -223,7 +226,8 @@ void given_user_with_grants_search_input_should_match_grants( mvc.perform( post(GLOBAL_SEARCH_URI + "/" + Scenario.class.getName()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.size()").value(expectedCount)) .andExpect(jsonPath("$.content[*].id", containsInAnyOrder(expectedIds.toArray()))); @@ -300,7 +304,8 @@ void given_user_with_specific_capability_and_search_input_should_return_expected post(GLOBAL_SEARCH_URI + "/" + Asset.class.getName()) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(searchPaginationInput)) - .with(authentication(auth))) + .with(authentication(auth)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.size()").value(expectedCount)) .andExpect(jsonPath("$.content[*].id", containsInAnyOrder(expectedIds.toArray()))); @@ -344,7 +349,8 @@ void given_user_with_specific_capability_and_search_input_should_return_expected post(GLOBAL_SEARCH_URI) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(term)) - .with(authentication(auth))) + .with(authentication(auth)) + .with(csrf())) .andExpect(status().is2xxSuccessful()); if (expectedCount == 0) { diff --git a/openaev-api/src/test/java/io/openaev/rest/tag_rule/TagRuleApiTest.java b/openaev-api/src/test/java/io/openaev/rest/tag_rule/TagRuleApiTest.java index 5aa0fbd7d58..0aed29c5715 100644 --- a/openaev-api/src/test/java/io/openaev/rest/tag_rule/TagRuleApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/tag_rule/TagRuleApiTest.java @@ -3,6 +3,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -60,7 +61,10 @@ void findTagRule() throws Exception { TagRule expected = createTagRule(tagId, List.of(assetGroupName)); String response = - mvc.perform(get(TAG_RULE_URI + "/" + expected.getId()).accept(MediaType.APPLICATION_JSON)) + mvc.perform( + get(TAG_RULE_URI + "/" + expected.getId()) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -79,7 +83,10 @@ void deleteTagRule() throws Exception { String assetGroupName = "assetGroupName"; String tagId = "tagName"; TagRule expected = createTagRule(tagId, List.of(assetGroupName)); - mvc.perform(delete(TAG_RULE_URI + "/" + expected.getId()).accept(MediaType.APPLICATION_JSON)) + mvc.perform( + delete(TAG_RULE_URI + "/" + expected.getId()) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -91,7 +98,8 @@ void deleteTagRule() throws Exception { @Test @WithMockUser(isAdmin = true) void deleteTagRule_WITH_unexisting_id() throws Exception { - mvc.perform(delete(TAG_RULE_URI + "/" + "randomid").accept(MediaType.APPLICATION_JSON)) + mvc.perform( + delete(TAG_RULE_URI + "/" + "randomid").accept(MediaType.APPLICATION_JSON).with(csrf())) .andExpect(status().isNotFound()) .andReturn() .getResponse() @@ -110,7 +118,8 @@ void createTagRule_with_nonExistingTag() throws Exception { post(TAG_RULE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -132,7 +141,8 @@ void createTagRule() throws Exception { post(TAG_RULE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -165,7 +175,8 @@ void updateTagRule() throws Exception { put(TAG_RULE_URI + "/" + toUpdate.getId()) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -197,7 +208,8 @@ void updateTagRule_WITH_non_existing_tag() throws Exception { put(TAG_RULE_URI + "/" + toUpdate.getId()) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -221,7 +233,8 @@ void updateTagRule_WITH_non_existing_id() throws Exception { put(TAG_RULE_URI + "/" + "randomid") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -240,7 +253,8 @@ void updateTagRule_WITH_non_existing_asset_group() throws Exception { put(TAG_RULE_URI + "/" + toUpdate.getId()) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -253,7 +267,8 @@ void findAllTagRules() throws Exception { mvc.perform( get(TAG_RULE_URI) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -282,7 +297,8 @@ void searchTagRule() throws Exception { post(TAG_RULE_URI + "/search") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() From 0d2a0ee7c68affc5549cc8060d1355eadb8972e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Tue, 24 Feb 2026 23:50:07 +0100 Subject: [PATCH 06/20] [backend] fix(csrf): tests (#1785) --- .../io/openaev/rest/asset_group/AssetGroupApiTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiTest.java b/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiTest.java index 72b030592c7..42b720e9b3b 100644 --- a/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiTest.java @@ -249,11 +249,11 @@ void given_validAssetGroupInputForNonexistentAssetGroup_should_returnNotFound() ServletException.class, () -> mvc.perform( - put(ASSET_GROUP_URI + "/" + nonexistentAssetGroupId) - .content(asJsonString(input)) - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) - .with(csrf())); + put(ASSET_GROUP_URI + "/" + nonexistentAssetGroupId) + .content(asJsonString(input)) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .with(csrf()))); } @DisplayName("Given existing assetGroup, should delete assetGroup successfully") From ac3ef5c79acd248a114d4796c209563858035be7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Wed, 25 Feb 2026 00:26:28 +0100 Subject: [PATCH 07/20] [backend] fix(csrf): tests (#1785) --- .../DetectionRemediationApiTest.java | 60 ++++++----- .../api/xtm_composer/XtmComposerApiTest.java | 49 ++++++--- .../killChainPhase/KillChainPhaseApiTest.java | 28 +++-- .../io/openaev/rest/AtomicTestingApiTest.java | 72 +++++++++---- .../java/io/openaev/rest/ChannelApiTest.java | 12 ++- .../rest/ConnectorInstanceApiTest.java | 58 ++++++---- .../java/io/openaev/rest/DomainApiTest.java | 7 +- .../io/openaev/rest/ExpectationApiTest.java | 15 +-- .../rest/ImportExportMapperApiTest.java | 13 ++- .../test/java/io/openaev/rest/LogApiTest.java | 7 +- .../java/io/openaev/rest/UserApiTest.java | 15 ++- .../io/openaev/rest/VulnerabilityApiTest.java | 11 +- .../java/io/openaev/rest/XtmHubApiTest.java | 10 +- .../asset_group/AssetGroupApiSearchTest.java | 19 ++-- .../attack_pattern/AttackPatternApiTest.java | 10 +- .../CustomDashboardWidgetApiTest.java | 30 +++--- .../rest/dashboard/DashboardApiTest.java | 34 ++++-- .../rest/exercise/ExerciseApiSearchTest.java | 31 ++++-- .../rest/exercise/ExerciseApiStatusTest.java | 25 +++-- .../rest/exercise/ExerciseApiTest.java | 34 ++++-- .../exercise/ExerciseInjectTestApiTest.java | 47 ++++---- .../rest/exercise/ExerciseTeamApiTest.java | 7 +- ...ciseApiImportWithoutExistingItemsTest.java | 76 ++++++++----- .../openaev/rest/finding/FindingApiTest.java | 4 +- .../io/openaev/rest/group/GroupApiTest.java | 16 ++- .../io/openaev/rest/inject/InjectApiTest.java | 69 ++++++++---- .../openaev/rest/inject/InjectExportTest.java | 39 ++++--- .../scenario/ScenarioInjectTestApiTest.java | 100 ++++++++++-------- .../OpenCTIJwtAuthenticationTest.java | 6 +- 29 files changed, 592 insertions(+), 312 deletions(-) diff --git a/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java b/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java index 90a4dddcb9e..81470799a22 100644 --- a/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java +++ b/openaev-api/src/test/java/io/openaev/api/detection_remediation/DetectionRemediationApiTest.java @@ -221,7 +221,8 @@ public void getDetectionRemediationRuleByPayloadWithBadDetectionRemediationAIRes + "/rules/" + CROWDSTRIKE_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isServiceUnavailable()); } @@ -269,7 +270,8 @@ public void getDetectionRemediationRuleByPayloadWithBadDetectionRemediationAIRes + "/rules/" + CROWDSTRIKE_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isBadGateway()); } @@ -317,7 +319,8 @@ public void getDetectionRemediationRuleByPayloadWithRetryDetectionRemediationAIR + "/rules/" + CROWDSTRIKE_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()); } @@ -396,7 +399,8 @@ public void getDetectionRemediationRuleBasedPayloadCommandCrowdStrikeWithRules() + "/rules/" + CROWDSTRIKE_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -469,7 +473,8 @@ public void getDetectionRemediationRuleBasedOnPayloadCommandCrowdStrike() throws + "/rules/" + CROWDSTRIKE_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -542,7 +547,8 @@ public void getDetectionRemediationRuleBasedOnPayloadCommandSplunk() throws Exce + "/rules/" + SPLUNK_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -597,7 +603,8 @@ public void getDetectionRemediationRuleBasedOnPayloadDnsResolutionCrowdStrike() + "/rules/" + CROWDSTRIKE_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -669,7 +676,8 @@ public void getDetectionRemediationRuleBasedOnPayloadDnsResolutionSplunk() throw + "/rules/" + SPLUNK_FRONTEND_NAME) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(input))) + .content(mapper.writeValueAsString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -889,12 +897,12 @@ public void getDetectionRemediationRuleByInjectUnknowCollectorType() throws Exce MockHttpServletResponse output = mockMvc .perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() - + "/collector/collector_name_unknow")) + + "/collector/collector_name_unknow") + .with(csrf())) .andReturn() .getResponse(); @@ -969,13 +977,13 @@ public void getDetectionRemediationRuleByInjectUnknowCollectorType() throws Exce // -- EXECUTE -- mockMvc .perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() + "/collector/" - + CROWDSTRIKE_FRONTEND_NAME)) + + CROWDSTRIKE_FRONTEND_NAME) + .with(csrf())) .andExpect(status().isOk()); } @@ -1005,13 +1013,13 @@ public void getDetectionRemediationRuleByInjectUnknowCollectorType() throws Exce String output = mockMvc .perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() + "/collector/" - + CROWDSTRIKE_FRONTEND_NAME)) + + CROWDSTRIKE_FRONTEND_NAME) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1073,13 +1081,13 @@ public void getDetectionRemediationRuleBasedOnInjectCommandSplunkWithoutDetectio String output = mockMvc .perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() + "/collector/" - + SPLUNK_FRONTEND_NAME)) + + SPLUNK_FRONTEND_NAME) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1126,13 +1134,13 @@ public void getDetectionRemediationRuleBasedOnInjectCommandSplunkWithoutDetectio String output = mockMvc .perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() + "/collector/" - + CROWDSTRIKE_FRONTEND_NAME)) + + CROWDSTRIKE_FRONTEND_NAME) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -1196,13 +1204,13 @@ public void getDetectionRemediationRuleBasedOnInjectCommandSplunkWithoutDetectio String output = mockMvc .perform( - post( - "/" + post("/" + DetectionRemediationApi.DETECTION_REMEDIATION_URI + "/rules/inject/" + inject.getId() + "/collector/" - + SPLUNK_FRONTEND_NAME)) + + SPLUNK_FRONTEND_NAME) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/api/xtm_composer/XtmComposerApiTest.java b/openaev-api/src/test/java/io/openaev/api/xtm_composer/XtmComposerApiTest.java index e53fbef309c..3bce5b703e9 100644 --- a/openaev-api/src/test/java/io/openaev/api/xtm_composer/XtmComposerApiTest.java +++ b/openaev-api/src/test/java/io/openaev/api/xtm_composer/XtmComposerApiTest.java @@ -9,6 +9,7 @@ import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -82,7 +83,8 @@ void givenXtmComposerUp_should_register() throws Exception { post(XTMCOMPOSER_URI + "/register") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -119,7 +121,8 @@ void givenXtmComposerAlreadyRegistered_should_updateRegistrationInfo() throws Ex post(XTMCOMPOSER_URI + "/register") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -136,7 +139,8 @@ void givenXtmComposerAlreadyRegistered_should_updateRegistrationInfo() throws Ex post(XTMCOMPOSER_URI + "/register") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -172,7 +176,8 @@ void should_refreshConnectivity() throws Exception { mvc.perform( put(XTMCOMPOSER_URI + "/composer-id-test/refresh-connectivity") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -195,7 +200,8 @@ void givenFakeXtmComposerId_should_throwErrorWhenRefreshConnectivity() throws Ex mvc.perform( put(XTMCOMPOSER_URI + "/fake-composer-id/refresh-connectivity") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isBadRequest()); } } @@ -216,7 +222,8 @@ void givenExpiredConnectivity_should_returnFalse() throws Exception { mvc.perform( get(XTMCOMPOSER_URI + "/reachable") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -237,7 +244,8 @@ void givenActiveConnection_should_returnTrue() throws Exception { mvc.perform( get(XTMCOMPOSER_URI + "/reachable") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -276,7 +284,8 @@ void givenFakeComposerId_should_throwError() throws Exception { mvc.perform( get(XTMCOMPOSER_URI + "/fake-composer-id/connector-instances") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -300,7 +309,8 @@ void should_retrieveAllInstancesManagedByXtmComposer() throws Exception { mvc.perform( get(XTMCOMPOSER_URI + "/composer-id-test/connector-instances") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -358,7 +368,8 @@ void givenFakeComposerId_should_throwError() throws Exception { + "/fake-composer-id/connector-instances/fake-instance-id/status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -385,7 +396,8 @@ void givenCurrentStatus_should_updateInstance() throws Exception { + "/status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -406,7 +418,8 @@ void givenCurrentStatus_should_updateInstance() throws Exception { + "/status") .content(asJsonString(input2)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -436,7 +449,8 @@ void givenFakeComposerId_should_throwError() throws Exception { + "/fake-composer-id/connector-instances/fake-instance-id/logs") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -471,7 +485,8 @@ void givenLogs_should_pushLogsForInstance() throws Exception { + "/logs") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -501,7 +516,8 @@ void givenFakeComposerId_should_throwError() throws Exception { + "/fake-composer-id/connector-instances/fake-instance-id/health-check") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -532,7 +548,8 @@ void givenHealthCheck_should_updateInstance() throws Exception { + "/health-check") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/killChainPhase/KillChainPhaseApiTest.java b/openaev-api/src/test/java/io/openaev/killChainPhase/KillChainPhaseApiTest.java index 7e56dc7b34e..f6d6b30799f 100644 --- a/openaev-api/src/test/java/io/openaev/killChainPhase/KillChainPhaseApiTest.java +++ b/openaev-api/src/test/java/io/openaev/killChainPhase/KillChainPhaseApiTest.java @@ -9,6 +9,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -91,7 +92,8 @@ void given_search_input_should_return_a_page_of_kill_chain_phases() throws Excep mvc.perform( post("/api/kill_chain_phases/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(PaginationFixture.getDefault().size(3).build()))) + .content(asJsonString(PaginationFixture.getDefault().size(3).build())) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(3)); } @@ -105,7 +107,8 @@ void given_a_bad_search_input_should_throw_bad_request() throws Exception { mvc.perform( post("/api/kill_chain_phases/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().isBadRequest()); } } @@ -125,7 +128,8 @@ void given_search_input_with_textsearch_should_return_a_page_of_kill_chain_phase mvc.perform( post("/api/kill_chain_phases/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -141,7 +145,8 @@ void given_search_input_with_textsearch_should_return_a_page_of_kill_chain_phase mvc.perform( post("/api/kill_chain_phases/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -156,7 +161,8 @@ void given_search_input_with_textsearch_with_spaces_should_return_a_page_of_kill mvc.perform( post("/api/kill_chain_phases/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(0)); } @@ -178,7 +184,8 @@ class FilteringPageOfKillChainPhases { mvc.perform( post("/api/kill_chain_phases/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -194,7 +201,8 @@ class FilteringPageOfKillChainPhases { mvc.perform( post("/api/kill_chain_phases/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -216,7 +224,8 @@ class SortingPageOfKillCHainPhases { mvc.perform( post("/api/kill_chain_phases/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[0].phase_name").value("name1")) .andExpect(jsonPath("$.content.[1].phase_name").value("name2")) @@ -236,7 +245,8 @@ void given_sort_input_should_return_a_page_of_kill_chain_phases_sort_by_name_des mvc.perform( post("/api/kill_chain_phases/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[0].phase_name").value("name3")) .andExpect(jsonPath("$.content.[1].phase_name").value("name2")) diff --git a/openaev-api/src/test/java/io/openaev/rest/AtomicTestingApiTest.java b/openaev-api/src/test/java/io/openaev/rest/AtomicTestingApiTest.java index d211ade1294..bc1440b4cf8 100644 --- a/openaev-api/src/test/java/io/openaev/rest/AtomicTestingApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/AtomicTestingApiTest.java @@ -4,6 +4,7 @@ import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -92,7 +93,8 @@ void findAnAtomicTestingWithoutStatus() throws Exception { String response = mvc.perform( get(ATOMIC_TESTINGS_URI + "/" + INJECT_WITHOUT_STATUS.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -121,7 +123,7 @@ void findAnAtomicTestingWithStatusAndCommandLines() throws Exception { """; String response = - mvc.perform(get(url).accept(MediaType.APPLICATION_JSON)) + mvc.perform(get(url).accept(MediaType.APPLICATION_JSON).with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -150,7 +152,8 @@ void createAndUpdateAnAtomicTesting() throws Exception { .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .content( - asJsonString(InjectFixture.createAtomicTesting("test", DOCUMENT.getId())))) + asJsonString(InjectFixture.createAtomicTesting("test", DOCUMENT.getId()))) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -158,7 +161,10 @@ void createAndUpdateAnAtomicTesting() throws Exception { assertNotNull(response); String newInjectId = JsonPath.read(response, "$.inject_id"); response = - mvc.perform(get(ATOMIC_TESTINGS_URI + "/" + newInjectId).accept(MediaType.APPLICATION_JSON)) + mvc.perform( + get(ATOMIC_TESTINGS_URI + "/" + newInjectId) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -173,14 +179,18 @@ void createAndUpdateAnAtomicTesting() throws Exception { put(ATOMIC_TESTINGS_URI + "/" + newInjectId) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) - .content(asJsonString(InjectFixture.createAtomicTesting("test2", null)))) + .content(asJsonString(InjectFixture.createAtomicTesting("test2", null))) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() .getContentAsString(); assertNotNull(response); response = - mvc.perform(get(ATOMIC_TESTINGS_URI + "/" + newInjectId).accept(MediaType.APPLICATION_JSON)) + mvc.perform( + get(ATOMIC_TESTINGS_URI + "/" + newInjectId) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -200,7 +210,8 @@ void duplicateAndDeleteAtomicTesting() throws Exception { mvc.perform( post(ATOMIC_TESTINGS_URI + "/" + INJECT_WITHOUT_STATUS.getId() + "/duplicate") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -209,17 +220,26 @@ void duplicateAndDeleteAtomicTesting() throws Exception { // Assert duplicate String newInjectId = JsonPath.read(response, "$.inject_id"); response = - mvc.perform(get(ATOMIC_TESTINGS_URI + "/" + newInjectId).accept(MediaType.APPLICATION_JSON)) + mvc.perform( + get(ATOMIC_TESTINGS_URI + "/" + newInjectId) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() .getContentAsString(); assertEquals(newInjectId, JsonPath.read(response, "$.inject_id")); // Delete - mvc.perform(delete(ATOMIC_TESTINGS_URI + "/" + newInjectId).accept(MediaType.APPLICATION_JSON)) + mvc.perform( + delete(ATOMIC_TESTINGS_URI + "/" + newInjectId) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // Assert delete - mvc.perform(get(ATOMIC_TESTINGS_URI + "/" + newInjectId).accept(MediaType.APPLICATION_JSON)) + mvc.perform( + get(ATOMIC_TESTINGS_URI + "/" + newInjectId) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()); } @@ -232,7 +252,7 @@ void launchAtomicTesting() throws Exception { entityManager.flush(); entityManager.clear(); - mvc.perform(post(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId() + "/launch")) + mvc.perform(post(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId() + "/launch").with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.inject_status.status_name").value("QUEUING")); } @@ -247,7 +267,8 @@ void relaunchAtomicTesting() throws Exception { .get(); String relaunchedInject = - mvc.perform(post(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId() + "/relaunch")) + mvc.perform( + post(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId() + "/relaunch").with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.inject_status.status_name").value("QUEUING")) .andReturn() @@ -255,9 +276,9 @@ void relaunchAtomicTesting() throws Exception { .getContentAsString(); String relaunchedInjectId = JsonPath.read(relaunchedInject, "$.inject_id"); - mvc.perform(get(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId())) + mvc.perform(get(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId()).with(csrf())) .andExpect(status().is4xxClientError()); - mvc.perform(get(ATOMIC_TESTINGS_URI + "/" + relaunchedInjectId)) + mvc.perform(get(ATOMIC_TESTINGS_URI + "/" + relaunchedInjectId).with(csrf())) .andExpect(status().is2xxSuccessful()); } @@ -272,7 +293,7 @@ void given_crowdstrike_should_not_LaunchAtomicTesting() throws Exception { Inject atomicTesting = getAtomicTestingWrapper(null, executorFixture.getCrowdstrikeExecutor()).persist().get(); - mvc.perform(post(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId() + "/launch")) + mvc.perform(post(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId() + "/launch").with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -287,7 +308,8 @@ void given_tanium_should_not_relaunchAtomicTesting() throws Exception { .persist() .get(); - mvc.perform(post(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId() + "/relaunch")) + mvc.perform( + post(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId() + "/relaunch").with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -302,7 +324,8 @@ void given_sentinelone_should_not_relaunchAtomicTesting() throws Exception { .persist() .get(); - mvc.perform(post(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId() + "/relaunch")) + mvc.perform( + post(ATOMIC_TESTINGS_URI + "/" + atomicTesting.getId() + "/relaunch").with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -318,7 +341,8 @@ void findPayloadOutputByInjectId() throws Exception { + "/" + INJECT_WITH_STATUS_AND_COMMAND_LINES.getId() + "/payload") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -419,7 +443,8 @@ public void mergedExpectationsHaveSupersetOfExpectationsAndMerged() throws Excep + "/target_results/" + endpointWrapper.get().getId() + "/types/ASSETS/merged") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -615,7 +640,8 @@ public void mergedExpectationsAreSeparatedByType() throws Exception { + "/target_results/" + endpointWrapper.get().getId() + "/types/ASSETS/merged") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -787,7 +813,8 @@ public void mergedExpectationsAgentsFromAsset() throws Exception { + endpointWrapper.get().getId() + "/asset_with_agents?expectationType=" + InjectExpectation.EXPECTATION_TYPE.DETECTION) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -830,7 +857,8 @@ public void mergedExpectationsAgentsFromAsset() throws Exception { + endpointWrapper.get().getId() + "/asset_with_agents?expectationType=" + InjectExpectation.EXPECTATION_TYPE.PREVENTION) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/ChannelApiTest.java b/openaev-api/src/test/java/io/openaev/rest/ChannelApiTest.java index db4d4eb0b2f..a1d9d09924f 100644 --- a/openaev-api/src/test/java/io/openaev/rest/ChannelApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/ChannelApiTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -85,7 +86,8 @@ void createArticleForScenarioTest() throws Exception { post(SCENARIO_URI + "/" + SCENARIO_ID + "/articles") .content(asJsonString(articleCreateInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -107,7 +109,8 @@ void retrieveArticlesForScenarioTest() throws Exception { this.mvc .perform( get(SCENARIO_URI + "/" + SCENARIO_ID + "/articles") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -135,7 +138,8 @@ void updateArticleForScenarioTest() throws Exception { put(SCENARIO_URI + "/" + SCENARIO_ID + "/articles/" + ARTICLE_ID) .content(asJsonString(articleUpdateInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -153,7 +157,7 @@ void updateArticleForScenarioTest() throws Exception { void deleteArticleForScenarioTest() throws Exception { // -- EXECUTE 1 ASSERT -- this.mvc - .perform(delete(SCENARIO_URI + "/" + SCENARIO_ID + "/articles/" + ARTICLE_ID)) + .perform(delete(SCENARIO_URI + "/" + SCENARIO_ID + "/articles/" + ARTICLE_ID).with(csrf())) .andExpect(status().is2xxSuccessful()); } } diff --git a/openaev-api/src/test/java/io/openaev/rest/ConnectorInstanceApiTest.java b/openaev-api/src/test/java/io/openaev/rest/ConnectorInstanceApiTest.java index de274202d4f..69237ca6e52 100644 --- a/openaev-api/src/test/java/io/openaev/rest/ConnectorInstanceApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/ConnectorInstanceApiTest.java @@ -11,6 +11,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -117,7 +118,8 @@ void givenNoEnterpriseEditionLicense_should_throwError() throws Exception { post(CONNECTOR_INSTANCE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -134,7 +136,8 @@ void givenConnectorSupportedByManager_should_throwErrorIfXtmComposerDown() throw post(CONNECTOR_INSTANCE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -155,7 +158,8 @@ void givenConnectorSupportedByManager_should_throwErrorIfXtmComposerDown() throw post(CONNECTOR_INSTANCE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -187,7 +191,8 @@ void duplicateCatalogConnectorInstance_should_throwError() throws Exception { post(CONNECTOR_INSTANCE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()) .andExpect( result -> { @@ -431,7 +436,8 @@ void should_successfullyCreateConnectorInstance() throws Exception { post(CONNECTOR_INSTANCE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -488,7 +494,8 @@ void givenId_shouldRetrievedConnectorInstance() throws Exception { mvc.perform( get(CONNECTOR_INSTANCE_URI + "/" + instance2.getId()) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -522,7 +529,8 @@ void givenConnectorInstanceId_shouldRetrievedAllConnectorInstanceConfigurations( mvc.perform( get(CONNECTOR_INSTANCE_URI + "/" + instance.getId() + "/configurations") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -554,7 +562,8 @@ void givenConnectorInstanceId_shouldNotRetrieveSecrets() throws Exception { mvc.perform( get(CONNECTOR_INSTANCE_URI + "/" + instance.getId() + "/configurations") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -584,7 +593,8 @@ void givenNoEnterpriseEditionLicense_should_throwError() throws Exception { put(CONNECTOR_INSTANCE_URI + "/fake-instance-id/configurations") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -602,7 +612,8 @@ void givenConnectorSupportedByManager_should_throwErrorIfXtmComposerDown() throw put(CONNECTOR_INSTANCE_URI + "/" + instance.getId() + "/configurations") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -623,7 +634,8 @@ void givenConnectorSupportedByManager_should_throwErrorIfXtmComposerDown() throw put(CONNECTOR_INSTANCE_URI + "/" + instance.getId() + "/configurations") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -680,7 +692,8 @@ void shouldSuccessfullyUpdateConnectorInstanceConfiguration() throws Exception { put(CONNECTOR_INSTANCE_URI + "/" + connectorInstance.getId() + "/configurations") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -719,7 +732,8 @@ void givenNoEnterpriseEditionLicense_should_throwError() throws Exception { put(CONNECTOR_INSTANCE_URI + "/fake-instance-id/requested-status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -738,7 +752,8 @@ void givenConnectorSupportedByManager_should_throwErrorIfXtmComposerDown() throw put(CONNECTOR_INSTANCE_URI + "/" + connectorInstance.getId() + "/requested-status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -760,7 +775,8 @@ void givenConnectorSupportedByManager_should_throwErrorIfXtmComposerDown() throw put(CONNECTOR_INSTANCE_URI + "/" + connectorInstance.getId() + "/requested-status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { @@ -790,7 +806,8 @@ void shouldSuccessfullyUpdateRequestedStatus() throws Exception { put(CONNECTOR_INSTANCE_URI + "/" + connectorInstance.getId() + "/requested-status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -808,7 +825,8 @@ void shouldSuccessfullyUpdateRequestedStatus() throws Exception { put(CONNECTOR_INSTANCE_URI + "/" + connectorInstance.getId() + "/requested-status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -843,7 +861,8 @@ void givenConnectorInstanceId_shouldRetrieveLogs() throws Exception { mvc.perform( get(CONNECTOR_INSTANCE_URI + "/" + connectorInstance1.getId() + "/logs") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -858,7 +877,8 @@ void givenConnectorInstanceId_shouldRetrieveLogs() throws Exception { mvc.perform( get(CONNECTOR_INSTANCE_URI + "/" + connectorInstance2.getId() + "/logs") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/DomainApiTest.java b/openaev-api/src/test/java/io/openaev/rest/DomainApiTest.java index 4c37ef0f6d5..79d2975ee80 100644 --- a/openaev-api/src/test/java/io/openaev/rest/DomainApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/DomainApiTest.java @@ -2,6 +2,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -45,7 +46,8 @@ public void whenDomainDoesNotExist_upsertCreatesAndReturnsDomain() throws Except post("/api/domains/{domainId}/upsert", "random-id") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -77,7 +79,8 @@ public void whenDomainExists_upsertReturnsExistingDomain() throws Exception { post("/api/domains/{domainId}/upsert", "random-id") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/ExpectationApiTest.java b/openaev-api/src/test/java/io/openaev/rest/ExpectationApiTest.java index 93c9dda06f5..e13a33e99e2 100644 --- a/openaev-api/src/test/java/io/openaev/rest/ExpectationApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/ExpectationApiTest.java @@ -919,7 +919,8 @@ void getAvailableInjectExpectationsForInjects() throws Exception { get(INJECTS_EXPECTATIONS_URI + "/available?injectorContractId=" + implantInjectorContract.getId()) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -969,7 +970,8 @@ private void callUpdateInjectExpectation( put(INJECTS_EXPECTATIONS_URI + "/" + injectExpectation.getId()) .content(asJsonString(expectationUpdateInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); } @@ -981,7 +983,8 @@ private void callUpdateInjectExpectationFromUI( put(EXPECTATIONS_URI + "/" + injectExpectation.getId()) .content(asJsonString(expectationUpdateInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); } @@ -990,13 +993,13 @@ private void callDeleteInjectExpectationFromUI( @NotNull final ExpectationUpdateInput expectationUpdateInput) throws Exception { mvc.perform( - put( - EXPECTATIONS_URI + put(EXPECTATIONS_URI + "/" + injectExpectation.getId() + "/" + expectationUpdateInput.getSourceId() - + "/delete")) + + "/delete") + .with(csrf())) .andExpect(status().is2xxSuccessful()); } } diff --git a/openaev-api/src/test/java/io/openaev/rest/ImportExportMapperApiTest.java b/openaev-api/src/test/java/io/openaev/rest/ImportExportMapperApiTest.java index 9b1ad264f13..0a313c27b7b 100644 --- a/openaev-api/src/test/java/io/openaev/rest/ImportExportMapperApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/ImportExportMapperApiTest.java @@ -3,6 +3,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import io.openaev.IntegrationTest; @@ -51,7 +52,8 @@ void testExportCsvWithEndpointsTarget() throws Exception { MockMvcRequestBuilders.post( "/api/mappers/export/csv?targetType=" + TargetType.ENDPOINTS) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(new SearchPaginationInput()))) + .content(asJsonString(new SearchPaginationInput())) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -73,7 +75,8 @@ void testExportCsvWithUnknownTarget() throws Exception { .perform( MockMvcRequestBuilders.post("/api/mappers/export/csv?targetType=" + TargetType.AGENT) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(new SearchPaginationInput()))) + .content(asJsonString(new SearchPaginationInput())) + .with(csrf())) .andExpect(status().is4xxClientError()) .andReturn() .getResponse() @@ -97,7 +100,8 @@ void testImportCsvWithEndpointsTarget() throws Exception { .perform( MockMvcRequestBuilders.multipart( "/api/mappers/import/csv?targetType=" + TargetType.ENDPOINTS) - .file(csvFile)) + .file(csvFile) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -133,7 +137,8 @@ void testImportCsvWithUnknownTarget() throws Exception { .perform( MockMvcRequestBuilders.multipart( "/api/mappers/import/csv?targetType=" + TargetType.AGENT) - .file(csvFile)) + .file(csvFile) + .with(csrf())) .andExpect(status().is4xxClientError()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/LogApiTest.java b/openaev-api/src/test/java/io/openaev/rest/LogApiTest.java index c729d82c0dc..3bab6258a4d 100644 --- a/openaev-api/src/test/java/io/openaev/rest/LogApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/LogApiTest.java @@ -3,6 +3,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -35,7 +36,8 @@ void given_input_should_return_200() throws Exception { post(LOG_URI) .content(asJsonString(logDetailsInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -55,7 +57,8 @@ void given_unsupported_level_should_return_400() throws Exception { post(LOG_URI + "/") .content(asJsonString(logDetailsInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()); } } diff --git a/openaev-api/src/test/java/io/openaev/rest/UserApiTest.java b/openaev-api/src/test/java/io/openaev/rest/UserApiTest.java index 60c95dc7122..9184da80e41 100644 --- a/openaev-api/src/test/java/io/openaev/rest/UserApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/UserApiTest.java @@ -363,13 +363,15 @@ void consumeTokenOnSuccessfulReset() throws Exception { mvc.perform( post("/api/reset") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()); mvc.perform( post("/api/reset/" + firstToken) .content(asJsonString(changePasswordInput)) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) // should be 401 Access Denied // but some black magic is changing the actual status code // see RestBehavior.java @@ -382,7 +384,8 @@ void consumeTokenOnSuccessfulReset() throws Exception { mvc.perform( post("/api/reset/" + firstToken) .content(asJsonString(changePasswordInput)) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) // should be 401 Access Denied // but some black magic is changing the actual status code // see RestBehavior.java @@ -401,7 +404,8 @@ void resetPasswordWithUnknownEmail() throws Exception { mvc.perform( post("/api/reset") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()); // -- ASSERT -- @@ -446,7 +450,8 @@ void given_user_with_several_grant_on_same_resource_should_return_highest_grant( mvc.perform( MockMvcRequestBuilders.put("/api/users/" + user.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(updateUserInput))) + .content(asJsonString(updateUserInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java b/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java index 5dbb7635a75..f56eceb5212 100644 --- a/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/VulnerabilityApiTest.java @@ -124,7 +124,8 @@ void shouldUpdateVulnerability() throws Exception { mvc.perform( put(VULNERABILITY_API + "/" + vulnerability.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(updateInput))) + .content(asJsonString(updateInput)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -158,7 +159,8 @@ void shouldBulkInsertVulnerabilities() throws Exception { post(VULNERABILITY_API + "/bulk") .content(asJsonString(inputs)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -178,7 +180,7 @@ void shouldDeleteVulnerability() throws Exception { vulnerability.setDescription("To be deleted"); vulnerabilityComposer.forVulnerability(vulnerability).persist(); - mvc.perform(delete(VULNERABILITY_API + "/" + vulnerability.getExternalId())) + mvc.perform(delete(VULNERABILITY_API + "/" + vulnerability.getExternalId()).with(csrf())) .andExpect(status().isOk()); Assertions.assertFalse( @@ -209,7 +211,8 @@ void shouldReturnVulnerabilitiesOnSearch() throws Exception { post(VULNERABILITY_API + "/search") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/XtmHubApiTest.java b/openaev-api/src/test/java/io/openaev/rest/XtmHubApiTest.java index fa630ab61a8..522603117eb 100644 --- a/openaev-api/src/test/java/io/openaev/rest/XtmHubApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/XtmHubApiTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -53,7 +54,8 @@ public void whenRegisterUpdateRegistrationData() throws Exception { put(XtmHubApi.XTMHUB_URI + "/register") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -94,7 +96,8 @@ public void whenUnregisterDeleteRegistrationData() throws Exception { mvc.perform( put(XtmHubApi.XTMHUB_URI + "/unregister") .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -144,7 +147,8 @@ public void whenContactUsSendMessage() throws Exception { post(XtmHubApi.XTMHUB_URI + "/contact-us") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiSearchTest.java b/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiSearchTest.java index 1658c48acee..626bae64428 100644 --- a/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiSearchTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/asset_group/AssetGroupApiSearchTest.java @@ -6,6 +6,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static java.lang.String.valueOf; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -69,7 +70,8 @@ void given_working_search_input_should_return_a_page_of_asset_groups() throws Ex mvc.perform( post(ASSET_GROUP_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(2)); } @@ -83,7 +85,8 @@ void given_not_working_search_input_should_return_a_page_of_asset_groups() throw mvc.perform( post(ASSET_GROUP_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(0)); } @@ -105,7 +108,8 @@ void given_sorting_input_by_name_should_return_a_page_of_asset_groups_sort_by_na mvc.perform( post(ASSET_GROUP_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[0].asset_group_name").value("Asset Group 1")) .andExpect(jsonPath("$.content.[1].asset_group_name").value("Asset Group 2")); @@ -125,7 +129,8 @@ void given_sorting_input_by_name_should_return_a_page_of_asset_groups_sort_by_na mvc.perform( post(ASSET_GROUP_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[0].asset_group_name").value("Asset Group 2")) .andExpect(jsonPath("$.content.[1].asset_group_name").value("Asset Group 1")); @@ -146,7 +151,8 @@ void given_filter_input_by_name_should_return_a_page_of_asset_groups_filter_by_n mvc.perform( post(ASSET_GROUP_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(2)); } @@ -162,7 +168,8 @@ void given_filter_input_by_sttaus_should_return_a_page_of_asset_groups_filter_by mvc.perform( post(ASSET_GROUP_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(2)); } diff --git a/openaev-api/src/test/java/io/openaev/rest/attack_pattern/AttackPatternApiTest.java b/openaev-api/src/test/java/io/openaev/rest/attack_pattern/AttackPatternApiTest.java index c0e6d34ee68..125b7fcc92d 100644 --- a/openaev-api/src/test/java/io/openaev/rest/attack_pattern/AttackPatternApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/attack_pattern/AttackPatternApiTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import io.openaev.IntegrationTest; @@ -60,7 +61,8 @@ void given_noTextAndNoFiles_should_throwAnException() { mvc.perform( multipart(ATTACK_PATTERN_URI + "/search-with-ai") .part(jsonPart) - .contentType(MediaType.MULTIPART_FORM_DATA))); + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf()))); assertTrue(exception.getMessage().contains("Either files or text must be provided")); } @@ -96,7 +98,8 @@ void given_moreThan5Files_should_throwAnException() { .file(mockFile4) .file(mockFile5) .file(mockFile6) - .contentType(MediaType.MULTIPART_FORM_DATA))); + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf()))); assertTrue(exception.getMessage().contains("Maximum of 5 files allowed")); } @@ -135,7 +138,8 @@ void given_textAndFiles_should_returnAttackPatternsIds() throws Exception { multipart(ATTACK_PATTERN_URI + "/search-with-ai") .part(jsonPart) .file(mockFile) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andReturn() .getResponse() .getContentAsString(); diff --git a/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardWidgetApiTest.java b/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardWidgetApiTest.java index dc9d52a707d..2d7ea05be28 100644 --- a/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardWidgetApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardWidgetApiTest.java @@ -8,6 +8,7 @@ import static io.openaev.utils.fixtures.WidgetFixture.NAME; import static io.openaev.utils.fixtures.WidgetFixture.createDefaultWidget; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -74,7 +75,8 @@ void given_valid_widget_input_when_creating_widget_should_return_created_widget( .perform( post(CUSTOM_DASHBOARDS_URI + "/" + customDashboard.getId() + "/widgets") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.widget_config.title").value(name)); } @@ -107,7 +109,8 @@ void given_valid_widget_input_when_creating_widget_should_return_created_widget( .perform( post(CUSTOM_DASHBOARDS_URI + "/" + customDashboard.getId() + "/widgets") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.widget_config.title").value(name)); } @@ -121,7 +124,8 @@ void given_widgets_should_return_all_widgets() throws Exception { // -- EXECUTE & ASSERT -- mockMvc - .perform(get(CUSTOM_DASHBOARDS_URI + "/" + customDashboard.getId() + "/widgets")) + .perform( + get(CUSTOM_DASHBOARDS_URI + "/" + customDashboard.getId() + "/widgets").with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.length()").value(1)) .andExpect(jsonPath("$[0].widget_config.title").value(NAME)); @@ -137,12 +141,12 @@ void given_widget_id_when_fetching_widget_should_return_widget() throws Exceptio // -- EXECUTE & ASSERT -- mockMvc .perform( - get( - CUSTOM_DASHBOARDS_URI + get(CUSTOM_DASHBOARDS_URI + "/" + customDashboard.getId() + "/widgets/" - + composer.get().getId())) + + composer.get().getId()) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.widget_config.title").value(NAME)); } @@ -169,7 +173,8 @@ void given_updated_widget_input_when_updating_widget_should_return_updated_widge + "/widgets/" + widget.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(widget))) + .content(asJsonString(widget)) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.widget_config.title").value(NAME)) .andExpect(jsonPath("$.widget_layout.widget_layout_x").value(10)); @@ -187,11 +192,12 @@ void given_widget_id_when_deleting_widget_should_return_no_content() throws Exce mockMvc .perform( delete( - CUSTOM_DASHBOARDS_URI - + "/" - + customDashboard.getId() - + "/widgets/" - + widget.getId())) + CUSTOM_DASHBOARDS_URI + + "/" + + customDashboard.getId() + + "/widgets/" + + widget.getId()) + .with(csrf())) .andExpect(status().isNoContent()); assertThat(repository.existsById(widget.getId())).isFalse(); diff --git a/openaev-api/src/test/java/io/openaev/rest/dashboard/DashboardApiTest.java b/openaev-api/src/test/java/io/openaev/rest/dashboard/DashboardApiTest.java index c7cc6b41a2e..ac0e249b5fd 100644 --- a/openaev-api/src/test/java/io/openaev/rest/dashboard/DashboardApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/dashboard/DashboardApiTest.java @@ -7,6 +7,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -103,7 +104,8 @@ void WhenNoSpecificFilter_ReturnAllEntitiesFromDimension() throws Exception { String response = mvc.perform( post(DASHBOARD_URI + "/entities/" + widget.getId()) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -154,7 +156,8 @@ void WhenSortingIsSpecified_ReturnEntitiesSortedAccordingly() throws Exception { String response = mvc.perform( post(DASHBOARD_URI + "/entities/" + widget.getId()) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -260,7 +263,8 @@ void WhenBindingWithDashboardParam_ParamIsAppliedToReturnedCollection() throws E .content( "{\"%s\":\"%s\"}" .formatted( - paramWrapper.get().getId(), exerciseWrapper1.get().getId()))) + paramWrapper.get().getId(), exerciseWrapper1.get().getId())) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -314,7 +318,8 @@ void countAllEntitiesWithNoSpecificFilter() throws Exception { mvc.perform( post(DASHBOARD_URI + "/count/" + widget.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -356,7 +361,8 @@ void countNoEntityWithNoSpecificFilter() throws Exception { mvc.perform( post(DASHBOARD_URI + "/count/" + widget.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -406,7 +412,8 @@ void countAllEntitiesWithSpecificFilter() throws Exception { mvc.perform( post(DASHBOARD_URI + "/count/" + widget.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -484,7 +491,8 @@ void countEntitiesWithDateRangeFilter() throws Exception { mvc.perform( post(DASHBOARD_URI + "/count/" + widget.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -576,7 +584,8 @@ void fetchSeriesForTemporalWidgets() throws Exception { mvc.perform( post(DASHBOARD_URI + "/series/" + widget.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -662,7 +671,8 @@ void fetchSeriesForStructuralWidgets() throws Exception { mvc.perform( post(DASHBOARD_URI + "/series/" + widget.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -723,7 +733,8 @@ void given_structuralEndpointHistogram_should_returnListOfWindowsEndpoint() thro mvc.perform( post(DASHBOARD_URI + "/entities-runtime/" + widget.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -815,7 +826,8 @@ void given_securityCoverageWidget_should_returnListOfInjectExpectations() throws mvc.perform( post(DASHBOARD_URI + "/entities-runtime/" + widget.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiSearchTest.java b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiSearchTest.java index 273d86f2820..8363b7b4a99 100644 --- a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiSearchTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiSearchTest.java @@ -7,6 +7,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static java.lang.String.valueOf; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -74,7 +75,8 @@ void given_working_search_input_should_return_a_page_of_exercises() throws Excep mvc.perform( post(EXERCISE_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -88,7 +90,8 @@ void given_not_working_search_input_should_return_a_page_of_exercises() throws E mvc.perform( post(EXERCISE_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(0)); } @@ -110,7 +113,8 @@ void given_sorting_input_by_name_should_return_a_page_of_exercises_sort_by_name( mvc.perform( post(EXERCISE_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[0].exercise_name").value("Crisis exercise")) .andExpect(jsonPath("$.content.[1].exercise_name").value("Incident response exercise")); @@ -133,7 +137,8 @@ void given_sorting_input_by_start_date_should_return_a_page_of_exercises_sort_by mvc.perform( post(EXERCISE_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.[1].exercise_name").value("Incident response exercise")) .andExpect(jsonPath("$.content.[0].exercise_name").value("Crisis exercise")); @@ -154,7 +159,8 @@ void given_filter_input_by_name_should_return_a_page_of_exercises_filter_by_name mvc.perform( post(EXERCISE_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -170,7 +176,8 @@ void given_filter_input_by_status_should_return_a_page_of_exercises_filter_by_st mvc.perform( post(EXERCISE_URI + "/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(2)); } @@ -184,7 +191,8 @@ void given_list_of_ids_select_exercises() throws Exception { mvc.perform( post(EXERCISE_URI + "/search-by-id") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(getExercisesInput))) + .content(asJsonString(getExercisesInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$").isArray()) .andExpect(jsonPath("$.length()").value(2)); @@ -200,7 +208,8 @@ void given_list_of_ids_select_exercises_with_capabilities() throws Exception { mvc.perform( post(EXERCISE_URI + "/search-by-id") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(getExercisesInput))) + .content(asJsonString(getExercisesInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$").isArray()) .andExpect(jsonPath("$.length()").value(2)); @@ -216,7 +225,8 @@ void given_list_of_ids_select_exercises_without_capabilities_no_grants() throws mvc.perform( post(EXERCISE_URI + "/search-by-id") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(getExercisesInput))) + .content(asJsonString(getExercisesInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$").isArray()) .andExpect(jsonPath("$.length()").value(0)); @@ -259,7 +269,8 @@ void given_list_of_ids_select_exercises_without_capabilities_with_grants() throw mvc.perform( post(EXERCISE_URI + "/search-by-id") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(getExercisesInput))) + .content(asJsonString(getExercisesInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$").isArray()) .andExpect(jsonPath("$.length()").value(1)); diff --git a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiStatusTest.java b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiStatusTest.java index a915ea26577..0717bb052b0 100644 --- a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiStatusTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiStatusTest.java @@ -9,6 +9,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.mockStatic; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -193,7 +194,8 @@ void manualStartExerciseTest() throws Exception { put(EXERCISE_URI + "/" + SCHEDULED_EXERCISE.getId() + "/status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -235,7 +237,8 @@ void rescheduledExerciseTest() throws Exception { put(EXERCISE_URI + "/" + CANCELED_EXERCISE.getId() + "/status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -263,7 +266,8 @@ void rescheduledExerciseFromFinishedStateTest() throws Exception { put(EXERCISE_URI + "/" + FINISHED_EXERCISE.getId() + "/status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -302,7 +306,8 @@ void runExerciseAfterPauseTest() throws Exception { put(EXERCISE_URI + "/" + PAUSED_EXERCISE.getId() + "/status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -357,7 +362,8 @@ void pauseAnExerciseTest() throws Exception { put(EXERCISE_URI + "/" + RUNNING_EXERCISE.getId() + "/status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -409,7 +415,8 @@ void cancelAnExerciseTest() throws Exception { put(EXERCISE_URI + "/" + exercise.getId() + "/status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -451,7 +458,8 @@ void checkExerciseNextStatusTest() { put(EXERCISE_URI + "/" + FINISHED_EXERCISE.getId() + "/status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON))); + .accept(MediaType.APPLICATION_JSON) + .with(csrf()))); String expectedMessage = "Exercise can't support moving to status CANCELED"; String actualMessage = exception.getMessage(); @@ -473,7 +481,8 @@ void rescheduledExerciseWithInjectTest() throws Exception { put(EXERCISE_URI + "/" + FINISHED_EXERCISE.getId() + "/status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiTest.java b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiTest.java index 3ec94031fc8..dd550090357 100644 --- a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiTest.java @@ -9,6 +9,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -116,7 +117,8 @@ void given_exercise_creation_should_set_default_custom_dashboard() throws Except post(EXERCISE_URI) .content(asJsonString(exerciseInput)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.exercise_name").value(name)) .andReturn() @@ -161,7 +163,8 @@ void retrievingPlayersByExercise() throws Exception { mvc.perform( get(EXERCISE_URI + "/" + exerciseSaved.getId() + "/players") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.length()").value(2)) .andExpect( @@ -189,7 +192,8 @@ void getGlobalScoreForExercises() throws Exception { mvc.perform( post(EXERCISE_URI + "/global-scores") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -221,7 +225,8 @@ void givenExerciseId_whenGettingScenarioFromExercise_thenReturnScenario() throws String response = mvc.perform( get(EXERCISE_URI + "/" + exerciseSaved.getId() + "/scenario") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -257,7 +262,8 @@ void checkIfRuleAppliesTest_WHEN_rule_found() throws Exception { post(EXERCISE_URI + "/" + exercise.getId() + "/check-rules") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -287,7 +293,8 @@ void checkIfRuleAppliesTest_WHEN_no_rule_found() throws Exception { post(EXERCISE_URI + "/" + exercise.getId() + "/check-rules") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -336,7 +343,8 @@ void given_crowdstrike_should_not_launchExercise() throws Exception { put(EXERCISE_URI + "/" + exercise.getId() + "/status") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -351,7 +359,8 @@ void given_tanium_should_not_scheduleExercise() throws Exception { put(EXERCISE_URI + "/" + exercise.getId() + "/start-date") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -366,7 +375,8 @@ void given_sentinelone_should_not_scheduleExercise() throws Exception { put(EXERCISE_URI + "/" + exercise.getId() + "/start-date") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -398,7 +408,8 @@ void given_taniumAsset_should_not_beAddedToScheduledExercise() throws Exception + exercise.getInjects().getFirst().getId()) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.message").value("LICENSE_RESTRICTION")); } @@ -437,7 +448,8 @@ void replacingTeamsShouldEnableNewTeamUsers() throws Exception { put(EXERCISE_URI + "/" + exerciseSaved.getId() + "/teams/replace") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(input)) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()); // -- ASSERT -- diff --git a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseInjectTestApiTest.java b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseInjectTestApiTest.java index 93ef7bf4d5e..fb28a378e86 100644 --- a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseInjectTestApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseInjectTestApiTest.java @@ -4,6 +4,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -93,7 +94,8 @@ void should_return_paginated_results_when_inject_tests_exist() throws Exception mvc.perform( post(EXERCISE_URI + "/{simulationId}/injects/test/search", simulation.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -111,7 +113,8 @@ void should_return_paginated_results_when_inject_tests_exist() throws Exception void should_return_test_status_by_testId() throws Exception { addGrantToCurrentUser( Grant.GRANT_RESOURCE_TYPE.SIMULATION, Grant.GRANT_TYPE.PLANNER, simulation.getId()); - mvc.perform(get(EXERCISE_URI + "/injects/test/{testId}", injectTestStatus1.getId())) + mvc.perform( + get(EXERCISE_URI + "/injects/test/{testId}", injectTestStatus1.getId()).with(csrf())) .andExpect(status().isOk()); } @@ -121,9 +124,10 @@ void should_return_test_status_by_testId() throws Exception { void should_return_test_status_when_testing_specific_inject() throws Exception { mvc.perform( get( - EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", - simulation.getId(), - inject1.getId())) + EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", + simulation.getId(), + inject1.getId()) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.inject_id").value(inject1.getId())); } @@ -142,7 +146,8 @@ void should_return_test_statuses_when_bulk_testing_with_inject_ids() throws Exce mvc.perform( post(EXERCISE_URI + "/{simulationId}/injects/test", simulation.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$").isArray()); } @@ -153,9 +158,10 @@ void should_return_test_statuses_when_bulk_testing_with_inject_ids() throws Exce void should_return_200_when_fetching_deleting_an_inject_test_status() throws Exception { mvc.perform( delete( - EXERCISE_URI + "/{simulationId}/injects/test/{testId}", - simulation.getId(), - injectTestStatus2.getId())) + EXERCISE_URI + "/{simulationId}/injects/test/{testId}", + simulation.getId(), + injectTestStatus2.getId()) + .with(csrf())) .andExpect(status().isOk()); } } @@ -174,7 +180,8 @@ void should_return_200_when_search_paginated_results() throws Exception { mvc.perform( post(EXERCISE_URI + "/{simulationId}/injects/test/search", simulation.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().isOk()); } @@ -184,7 +191,8 @@ void should_return_200_when_search_paginated_results() throws Exception { void should_return_200_when_search_by_testId() throws Exception { addGrantToCurrentUser( Grant.GRANT_RESOURCE_TYPE.SIMULATION, Grant.GRANT_TYPE.OBSERVER, simulation.getId()); - mvc.perform(get(EXERCISE_URI + "/injects/test/{testId}", injectTestStatus1.getId())) + mvc.perform( + get(EXERCISE_URI + "/injects/test/{testId}", injectTestStatus1.getId()).with(csrf())) .andExpect(status().isOk()); } @@ -194,9 +202,10 @@ void should_return_200_when_search_by_testId() throws Exception { void should_return_403_when_testing_specific_inject() throws Exception { mvc.perform( get( - EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", - simulation.getId(), - inject1.getId())) + EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", + simulation.getId(), + inject1.getId()) + .with(csrf())) .andExpect(status().isForbidden()); } @@ -214,7 +223,8 @@ void should_return_403_when_bulk_testing_with_inject_ids() throws Exception { mvc.perform( post(EXERCISE_URI + "/{simulationId}/injects/test", simulation.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isForbidden()); } @@ -226,9 +236,10 @@ void should_return_403_when_fetching_deleted_inject_test_status() throws Excepti Grant.GRANT_RESOURCE_TYPE.SIMULATION, Grant.GRANT_TYPE.OBSERVER, simulation.getId()); mvc.perform( delete( - EXERCISE_URI + "/{simulationId}/injects/test/{testId}", - simulation.getId(), - injectTestStatus1.getId())) + EXERCISE_URI + "/{simulationId}/injects/test/{testId}", + simulation.getId(), + injectTestStatus1.getId()) + .with(csrf())) .andExpect(status().isForbidden()); } } diff --git a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseTeamApiTest.java b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseTeamApiTest.java index 39cd3279038..77cdc0c7af9 100644 --- a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseTeamApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseTeamApiTest.java @@ -4,6 +4,7 @@ import static io.openaev.utils.JsonTestUtils.asJsonString; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -65,7 +66,8 @@ void givenContextualOnlyFalse_whenSearchingTeams_shouldReturnGlobalAndExerciseTe + exerciseCreated.getId() + "/teams/search?contextualOnly=false") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.size()").value(2)) .andExpect( @@ -109,7 +111,8 @@ void givenContextualOnlyTrue_whenSearchingTeams_shouldReturnOnlyExerciseTeams() + exerciseCreated.getId() + "/teams/search?contextualOnly=true") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.content.size()").value(2)) .andExpect( diff --git a/openaev-api/src/test/java/io/openaev/rest/exercise/imports/ExerciseApiImportWithoutExistingItemsTest.java b/openaev-api/src/test/java/io/openaev/rest/exercise/imports/ExerciseApiImportWithoutExistingItemsTest.java index 86d141e07ad..d6b1612b425 100644 --- a/openaev-api/src/test/java/io/openaev/rest/exercise/imports/ExerciseApiImportWithoutExistingItemsTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/exercise/imports/ExerciseApiImportWithoutExistingItemsTest.java @@ -3,6 +3,7 @@ import static io.openaev.rest.exercise.ExerciseApi.EXERCISE_URI; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -182,7 +183,8 @@ private byte[] doExport(ExerciseComposer.Composer composer) throws Exception { mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -220,7 +222,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -259,7 +262,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -289,7 +293,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -335,7 +340,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -369,7 +375,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -408,7 +415,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -447,7 +455,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -495,7 +504,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -526,7 +536,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -571,7 +582,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -604,7 +616,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -642,7 +655,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -674,7 +688,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -715,7 +730,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -749,7 +765,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -791,7 +808,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -822,7 +840,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -861,7 +880,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -892,7 +912,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -942,7 +963,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -973,7 +995,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -1018,7 +1041,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -1049,7 +1073,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -1100,7 +1125,8 @@ public void given_a_valid_export_zip_file_given_no_preexisting_objects_create_ne mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations diff --git a/openaev-api/src/test/java/io/openaev/rest/finding/FindingApiTest.java b/openaev-api/src/test/java/io/openaev/rest/finding/FindingApiTest.java index cccb9a10de7..09bc2b4186c 100644 --- a/openaev-api/src/test/java/io/openaev/rest/finding/FindingApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/finding/FindingApiTest.java @@ -6,6 +6,7 @@ import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -946,7 +947,8 @@ private ResultActions performCallbackRequest(String uri, SearchPaginationInput i post(uri) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); } } diff --git a/openaev-api/src/test/java/io/openaev/rest/group/GroupApiTest.java b/openaev-api/src/test/java/io/openaev/rest/group/GroupApiTest.java index be49d7658bc..731b1952f8b 100644 --- a/openaev-api/src/test/java/io/openaev/rest/group/GroupApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/group/GroupApiTest.java @@ -4,6 +4,7 @@ import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -63,7 +64,8 @@ void canCreateAGroupWithInput() throws Exception { post(GROUP_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -100,7 +102,8 @@ void canUpdateAGroupWithInput() throws Exception { put(GROUP_URI + "/" + groupWrapper.get().getId() + "/information") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -138,7 +141,8 @@ void test_updateGroupRoles() throws Exception { put(GROUP_URI + "/" + group.getId() + "/roles") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -159,7 +163,8 @@ void test_updateGroupRoles_WITH_unexisting_role_id() throws Exception { put(GROUP_URI + "/" + group.getId() + "/roles") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } @@ -172,7 +177,8 @@ void test_updateGroupRoles_WITH_unexisting_group_id() throws Exception { put(GROUP_URI + "/randomid/roles") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()); } } diff --git a/openaev-api/src/test/java/io/openaev/rest/inject/InjectApiTest.java b/openaev-api/src/test/java/io/openaev/rest/inject/InjectApiTest.java index e18accf898e..d1240658c53 100644 --- a/openaev-api/src/test/java/io/openaev/rest/inject/InjectApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/inject/InjectApiTest.java @@ -303,7 +303,8 @@ void updateInjectForSimulationTest() throws Exception { put(INJECT_URI + "/" + EXERCISE.getId() + "/" + injectToUpdate.getId()) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -354,7 +355,8 @@ void executeEmailInjectForExerciseTest() throws Exception { mvc.perform( multipart(EXERCISE_URI + "/" + EXERCISE.getId() + "/inject") .file(inputJson) - .file(fileJson)) + .file(fileJson) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -398,7 +400,10 @@ void executeEmailInjectForExerciseWithNoTeam() throws Exception { // -- EXECUTE -- String response = - mvc.perform(multipart(EXERCISE_URI + "/" + EXERCISE.getId() + "/inject").file(inputJson)) + mvc.perform( + multipart(EXERCISE_URI + "/" + EXERCISE.getId() + "/inject") + .file(inputJson) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -431,7 +436,10 @@ void executeEmailInjectForExerciseWithNoContentTest() throws Exception { // -- EXECUTION -- String response = - mvc.perform(multipart(EXERCISE_URI + "/" + EXERCISE.getId() + "/inject").file(inputJson)) + mvc.perform( + multipart(EXERCISE_URI + "/" + EXERCISE.getId() + "/inject") + .file(inputJson) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -526,7 +534,10 @@ void deleteInjectsForExerciseTest() throws Exception { // -- EXECUTE -- mvc.perform( - delete(INJECT_URI).content(asJsonString(input)).contentType(MediaType.APPLICATION_JSON)) + delete(INJECT_URI) + .content(asJsonString(input)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // -- ASSERT -- @@ -601,7 +612,8 @@ void getExecutablePayloadInjectWithArguments() throws Exception { String response = mvc.perform( get(INJECT_URI + "/" + injectSaved.getId() + "/fakeId/executable-payload") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -702,7 +714,8 @@ void given_targetedAssetArgument_should_replaceByAssetIDs() throws Exception { String response = mvc.perform( get(INJECT_URI + "/" + injectSaved.getId() + "/fakeId/executable-payload") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -763,7 +776,8 @@ void calling_RetrievingExecutablePayload_should_setStartDateSignature() throws E + "/" + agentWrapper.get().getId() + "/executable-payload") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); entityManager.flush(); @@ -819,7 +833,8 @@ void getExecutableObfuscatePayloadInject() throws Exception { String response = mvc.perform( get(INJECT_URI + "/" + injectSaved.getId() + "/fakeagentID/executable-payload") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -871,7 +886,8 @@ void getExecutableCmdPayloadInject() throws Exception { String response = mvc.perform( get(INJECT_URI + "/" + injectSaved.getId() + "/fakeagentID/executable-payload") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -925,7 +941,8 @@ void shouldNotGetExecutableCmdPayloadInject() throws Exception { () -> { mvc.perform( get(INJECT_URI + "/" + injectSaved.getId() + "/fakeagentID/executable-payload") - .accept(MediaType.APPLICATION_JSON)); + .accept(MediaType.APPLICATION_JSON) + .with(csrf())); }); } } @@ -952,7 +969,8 @@ private void performAgentlessCallbackRequest(String injectId, InjectExecutionInp post(INJECT_URI + "/execution/callback/" + injectId) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -965,7 +983,8 @@ private void performCallbackRequest(String agentId, String injectId, InjectExecu post(INJECT_URI + "/execution/" + agentId + "/callback/" + injectId) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() @@ -3521,7 +3540,7 @@ private Inject buildInjectWithTraces(List trace private String performGetRequest( String baseUri, String injectId, String targetId, TargetType targetType) throws Exception { MockHttpServletRequestBuilder requestBuilder = - get(baseUri).accept(MediaType.APPLICATION_JSON).param("injectId", injectId); + get(baseUri).accept(MediaType.APPLICATION_JSON).param("injectId", injectId).with(csrf()); if (targetId != null) { requestBuilder.param("targetId", targetId); @@ -3715,7 +3734,8 @@ void shouldReturn400WhenTargetTypeIsUnsupported() throws Exception { .accept(MediaType.APPLICATION_JSON) .param("injectId", "someInjectId") .param("targetId", "someTargetId") - .param("targetType", TargetType.ASSETS_GROUPS.name()); + .param("targetType", TargetType.ASSETS_GROUPS.name()) + .with(csrf()); mvc.perform(requestBuilder) .andExpect(status().isBadRequest()) @@ -3786,7 +3806,8 @@ void shouldReturnDropFileDocumentsForInjectIdAndPayloadId() throws Exception { // EXECUTE MockHttpServletRequestBuilder requestBuilder = get(INJECT_URI + "/" + inject.getId() + "/payload/" + payload.getId() + "/documents") - .accept(MediaType.APPLICATION_JSON); + .accept(MediaType.APPLICATION_JSON) + .with(csrf()); // ASSERT String response = @@ -3809,7 +3830,8 @@ void shouldReturnExecutableDocumentsForInjectIdAndPayloadId() throws Exception { // EXECUTE MockHttpServletRequestBuilder requestBuilder = get(INJECT_URI + "/" + inject.getId() + "/payload/" + payload.getId() + "/documents") - .accept(MediaType.APPLICATION_JSON); + .accept(MediaType.APPLICATION_JSON) + .with(csrf()); // ASSERT String response = @@ -3826,7 +3848,9 @@ void shouldReturnExecutableDocumentsForInjectIdAndPayloadId() throws Exception { void shouldReturnElementNotFoundExceptionForUnknownInject() throws Exception { // EXECUTE MockHttpServletRequestBuilder requestBuilder = - get(INJECT_URI + "/TEST/payload/TEST/documents").accept(MediaType.APPLICATION_JSON); + get(INJECT_URI + "/TEST/payload/TEST/documents") + .accept(MediaType.APPLICATION_JSON) + .with(csrf()); // ASSERT String response = @@ -3849,7 +3873,8 @@ void shouldReturnElementNotFoundExceptionForInjectWithoutPayload() throws Except // EXECUTE MockHttpServletRequestBuilder requestBuilder = get(INJECT_URI + "/" + inject.getId() + "/payload/TEST/documents") - .accept(MediaType.APPLICATION_JSON); + .accept(MediaType.APPLICATION_JSON) + .with(csrf()); // ASSERT String response = @@ -3872,7 +3897,8 @@ void shouldReturnBadRequestExceptionWhenInjectAndPayloadMismatch() throws Except // EXECUTE MockHttpServletRequestBuilder requestBuilder = get(INJECT_URI + "/" + inject.getId() + "/payload/TEST/documents") - .accept(MediaType.APPLICATION_JSON); + .accept(MediaType.APPLICATION_JSON) + .with(csrf()); // ASSERT mvc.perform(requestBuilder).andExpect(status().isBadRequest()); @@ -3915,7 +3941,8 @@ void shouldReturnListCollectorRelatedToDetectionRemediationsWhenInjectIdIsGiven( // EXECUTE MockHttpServletRequestBuilder requestBuilder = get(ATOMIC_TESTING_URI + "/" + inject.getId() + "/collectors") - .accept(MediaType.APPLICATION_JSON); + .accept(MediaType.APPLICATION_JSON) + .with(csrf()); // ASSERT String result = diff --git a/openaev-api/src/test/java/io/openaev/rest/inject/InjectExportTest.java b/openaev-api/src/test/java/io/openaev/rest/inject/InjectExportTest.java index cd4e7c1c1ee..7e1647fa2a0 100644 --- a/openaev-api/src/test/java/io/openaev/rest/inject/InjectExportTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/inject/InjectExportTest.java @@ -7,6 +7,7 @@ import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; import static org.junit.jupiter.api.Assertions.*; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -350,7 +351,7 @@ public class WhenUnauthenticated { @Test @DisplayName("Return UNAUTHORISED") public void whenLackingAuthorisation_returnUnauthorised() throws Exception { - mvc.perform(post(INJECT_URI + "/export").contentType(MediaType.APPLICATION_JSON)) + mvc.perform(post(INJECT_URI + "/export").contentType(MediaType.APPLICATION_JSON).with(csrf())) .andExpect(status().isUnauthorized()); } } @@ -381,7 +382,8 @@ public void whenLackingOBSERVERGrantOnSomeScenariosReturnNOTFOUND() throws Excep mvc.perform( post(INJECT_EXPORT_URI) .content(mapper.writeValueAsString(input)) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()) .andReturn() .getResponse() @@ -429,7 +431,8 @@ public void whenLackingOBSERVERGrantOnSomeExercisesReturnNOTFOUND() throws Excep mvc.perform( post(INJECT_EXPORT_URI) .content(mapper.writeValueAsString(input)) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()) .andReturn() .getResponse() @@ -496,7 +499,8 @@ void given_user_with_grants_search_input_should_match_grants() throws Exception post(INJECT_EXPORT_SEARCH_URI) .content(mapper.writeValueAsString(exportInput)) .contentType(MediaType.APPLICATION_JSON) - .with(authentication(auth))) + .with(authentication(auth)) + .with(csrf())) .andExpect(status().isOk()) .andExpect(header().string(HttpHeaders.CONTENT_TYPE, "application/zip")) .andExpect(header().exists(HttpHeaders.CONTENT_DISPOSITION)) @@ -575,7 +579,8 @@ public void whenLackingOBSERVERGrantOnExerciseReturnNotFound() throws Exception mvc.perform( post(INJECT_EXPORT_SEARCH_URI) .content(mapper.writeValueAsString(exportInput)) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()) .andReturn() .getResponse() @@ -607,7 +612,8 @@ public void withOBSERVERGrantOnExerciseReturnInjects() throws Exception { mvc.perform( post(INJECT_EXPORT_SEARCH_URI) .content(mapper.writeValueAsString(exportInput)) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -654,7 +660,8 @@ public void withOBSERVERGrantOnExerciseWithExclusionReturnCorrectInjects() throw mvc.perform( post(INJECT_EXPORT_SEARCH_URI) .content(mapper.writeValueAsString(exportInput)) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -699,7 +706,8 @@ public void whenIndividualExportInjectIsNotFound_returnNotFound() throws Excepti mvc.perform( post("/api/injects/ " + UUID.randomUUID().toString() + "/inject_export") .content(mapper.writeValueAsString(new InjectIndividualExportRequestInput())) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()) .andReturn() .getResponse() @@ -716,7 +724,8 @@ public void returnedZipFileContainsJsonWithCorrectInjects() throws Exception { mvc.perform( post("/api/injects/" + inject.getId() + "/inject_export") .content(mapper.writeValueAsString(new InjectIndividualExportRequestInput())) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -758,7 +767,8 @@ public void whenSingleTargetInjectIsNotFound_returnNotFound() throws Exception { mvc.perform( post(INJECT_EXPORT_URI) .content(mapper.writeValueAsString(input)) - .contentType(MediaType.APPLICATION_JSON)) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isNotFound()) .andReturn() .getResponse() @@ -776,7 +786,8 @@ private byte[] doExport() throws Exception { return mvc.perform( post(INJECT_EXPORT_URI) .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(createDefaultInjectExportRequestInput()))) + .content(mapper.writeValueAsString(createDefaultInjectExportRequestInput())) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -930,7 +941,8 @@ private byte[] doExport() throws Exception { .contentType(MediaType.APPLICATION_JSON) .content( mapper.writeValueAsString( - createDefaultInjectExportRequestInput(false, true, false)))) + createDefaultInjectExportRequestInput(false, true, false))) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -977,7 +989,8 @@ private byte[] doExport() throws Exception { .contentType(MediaType.APPLICATION_JSON) .content( mapper.writeValueAsString( - createDefaultInjectExportRequestInput(true, false, false)))) + createDefaultInjectExportRequestInput(true, false, false))) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectTestApiTest.java b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectTestApiTest.java index ccf11b838a9..1d71f0a4bbe 100644 --- a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectTestApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioInjectTestApiTest.java @@ -9,6 +9,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -111,9 +112,10 @@ public void scenarioVariableIsInterpolated() throws Exception { Mockito.doCallRealMethod().when(mailSender).send((MimeMessage) any()); mvc.perform( get( - SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", - scenarioWithEmailInjectWrapper.get().getId(), - scenarioWithEmailInjectWrapper.get().getInjects().getFirst().getId())) + SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", + scenarioWithEmailInjectWrapper.get().getId(), + scenarioWithEmailInjectWrapper.get().getInjects().getFirst().getId()) + .with(csrf())) .andExpect(status().isOk()); verify(mailSender).send(argument.capture()); @@ -151,9 +153,10 @@ public void userVariableIsInterpolatedInScenarioInjectTest() throws Exception { Mockito.doCallRealMethod().when(mailSender).send((MimeMessage) any()); mvc.perform( get( - SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", - scenarioWithEmailInjectWrapper.get().getId(), - scenarioWithEmailInjectWrapper.get().getInjects().getFirst().getId())) + SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", + scenarioWithEmailInjectWrapper.get().getId(), + scenarioWithEmailInjectWrapper.get().getInjects().getFirst().getId()) + .with(csrf())) .andExpect(status().isOk()); verify(mailSender).send(argument.capture()); @@ -198,9 +201,10 @@ public void simulationVariableIsInterpolated() throws Exception { Mockito.doCallRealMethod().when(mailSender).send((MimeMessage) any()); mvc.perform( get( - EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", - simulationWithEmailInjectWrapper.get().getId(), - simulationWithEmailInjectWrapper.get().getInjects().getFirst().getId())) + EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", + simulationWithEmailInjectWrapper.get().getId(), + simulationWithEmailInjectWrapper.get().getInjects().getFirst().getId()) + .with(csrf())) .andExpect(status().isOk()); verify(mailSender).send(argument.capture()); @@ -240,9 +244,10 @@ public void userVariableIsInterpolatedInSimulationInjectTest() throws Exception Mockito.doCallRealMethod().when(mailSender).send((MimeMessage) any()); mvc.perform( get( - EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", - simulationWithEmailInjectWrapper.get().getId(), - simulationWithEmailInjectWrapper.get().getInjects().getFirst().getId())) + EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", + simulationWithEmailInjectWrapper.get().getId(), + simulationWithEmailInjectWrapper.get().getInjects().getFirst().getId()) + .with(csrf())) .andReturn(); // .andExpect(status().isOk()); @@ -300,9 +305,10 @@ public void scenarioVariableIsInterpolated() throws Exception { Mockito.doCallRealMethod().when(mailSender).send((MimeMessage) any()); mvc.perform( get( - SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", - scenarioWithEmailInjectWrapper.get().getId(), - scenarioWithEmailInjectWrapper.get().getInjects().getFirst().getId())) + SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", + scenarioWithEmailInjectWrapper.get().getId(), + scenarioWithEmailInjectWrapper.get().getInjects().getFirst().getId()) + .with(csrf())) .andExpect(status().isOk()); verify(mailSender).send(argument.capture()); @@ -341,9 +347,10 @@ public void userVariableIsInterpolatedInScenarioInjectTest() throws Exception { Mockito.doCallRealMethod().when(mailSender).send((MimeMessage) any()); mvc.perform( get( - SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", - scenarioWithEmailInjectWrapper.get().getId(), - scenarioWithEmailInjectWrapper.get().getInjects().getFirst().getId())) + SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", + scenarioWithEmailInjectWrapper.get().getId(), + scenarioWithEmailInjectWrapper.get().getInjects().getFirst().getId()) + .with(csrf())) .andExpect(status().isOk()); verify(mailSender).send(argument.capture()); @@ -388,9 +395,10 @@ public void simulationVariableIsInterpolated() throws Exception { Mockito.doCallRealMethod().when(mailSender).send((MimeMessage) any()); mvc.perform( get( - EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", - simulationWithEmailInjectWrapper.get().getId(), - simulationWithEmailInjectWrapper.get().getInjects().getFirst().getId())) + EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", + simulationWithEmailInjectWrapper.get().getId(), + simulationWithEmailInjectWrapper.get().getInjects().getFirst().getId()) + .with(csrf())) .andExpect(status().isOk()); verify(mailSender).send(argument.capture()); @@ -431,9 +439,10 @@ public void userVariableIsInterpolatedInSimulationInjectTest() throws Exception Mockito.doCallRealMethod().when(mailSender).send((MimeMessage) any()); mvc.perform( get( - EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", - simulationWithEmailInjectWrapper.get().getId(), - simulationWithEmailInjectWrapper.get().getInjects().getFirst().getId())) + EXERCISE_URI + "/{simulationId}/injects/{injectId}/test", + simulationWithEmailInjectWrapper.get().getId(), + simulationWithEmailInjectWrapper.get().getInjects().getFirst().getId()) + .with(csrf())) .andExpect(status().isOk()); verify(mailSender).send(argument.capture()); @@ -500,7 +509,8 @@ void should_return_paginated_results_when_inject_tests_exist() throws Exception SCENARIO_URI + "/{scenarioId}/injects/test/search", scenarioWrapper.persist().get().getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -517,9 +527,8 @@ void should_return_paginated_results_when_inject_tests_exist() throws Exception @WithMockUser(withCapabilities = {Capability.ACCESS_ASSESSMENT}) void should_return_test_status_by_testId() throws Exception { mvc.perform( - get( - SCENARIO_URI + "/injects/test/{testId}", - injectTestStatus1Wrapper.get().getId())) + get(SCENARIO_URI + "/injects/test/{testId}", injectTestStatus1Wrapper.get().getId()) + .with(csrf())) .andExpect(status().isOk()); } @@ -529,9 +538,10 @@ void should_return_test_status_by_testId() throws Exception { void should_return_test_status_when_testing_specific_inject() throws Exception { mvc.perform( get( - SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", - scenarioWrapper.persist().get().getId(), - inject1Wrapper.get().getId())) + SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", + scenarioWrapper.persist().get().getId(), + inject1Wrapper.get().getId()) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.inject_id").value(inject1Wrapper.get().getId())); } @@ -549,7 +559,8 @@ void should_return_test_statuses_when_bulk_testing_with_inject_ids() throws Exce mvc.perform( post(SCENARIO_URI + "/{scenarioId}/injects/test", testScenario.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$").isArray()); } @@ -560,9 +571,10 @@ void should_return_test_statuses_when_bulk_testing_with_inject_ids() throws Exce void should_return_200_when_fetching_deleting_an_inject_test_status() throws Exception { mvc.perform( delete( - SCENARIO_URI + "/{scenarioId}/injects/test/{testId}", - scenarioWrapper.persist().get().getId(), - injectTestStatus2Wrapper.get().getId())) + SCENARIO_URI + "/{scenarioId}/injects/test/{testId}", + scenarioWrapper.persist().get().getId(), + injectTestStatus2Wrapper.get().getId()) + .with(csrf())) .andExpect(status().isOk()); } } @@ -581,7 +593,8 @@ void should_return_403_when_search_paginated_results() throws Exception { SCENARIO_URI + "/{scenarioId}/injects/test/search", scenarioWrapper.persist().get().getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().isForbidden()); } @@ -590,9 +603,8 @@ void should_return_403_when_search_paginated_results() throws Exception { @WithMockUser(withCapabilities = {Capability.ACCESS_ASSESSMENT}) void should_return_200_when_search_by_testId() throws Exception { mvc.perform( - get( - SCENARIO_URI + "/injects/test/{testId}", - injectTestStatus1Wrapper.get().getId())) + get(SCENARIO_URI + "/injects/test/{testId}", injectTestStatus1Wrapper.get().getId()) + .with(csrf())) .andExpect(status().isOk()); } @@ -601,9 +613,10 @@ void should_return_200_when_search_by_testId() throws Exception { void should_return_403_when_testing_specific_inject() throws Exception { mvc.perform( get( - SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", - scenarioWrapper.persist().get().getId(), - inject1Wrapper.get().getId())) + SCENARIO_URI + "/{scenarioId}/injects/{injectId}/test", + scenarioWrapper.persist().get().getId(), + inject1Wrapper.get().getId()) + .with(csrf())) .andExpect(status().isForbidden()); } @@ -620,7 +633,8 @@ void should_return_403_when_bulk_testing_with_inject_ids() throws Exception { SCENARIO_URI + "/{scenarioId}/injects/test", scenarioWrapper.persist().get().getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isForbidden()); } } diff --git a/openaev-api/src/test/java/io/openaev/security/OpenCTIJwtAuthenticationTest.java b/openaev-api/src/test/java/io/openaev/security/OpenCTIJwtAuthenticationTest.java index dc2d3ea437e..420b9ea27c3 100644 --- a/openaev-api/src/test/java/io/openaev/security/OpenCTIJwtAuthenticationTest.java +++ b/openaev-api/src/test/java/io/openaev/security/OpenCTIJwtAuthenticationTest.java @@ -3,6 +3,7 @@ import static io.openaev.api.stix_process.StixApi.STIX_URI; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -123,7 +124,10 @@ void processBundle_authorizationOpenCti( entityManager.flush(); var request = - post(STIX_URI + "/process-bundle").contentType(MediaType.APPLICATION_JSON).content(""); + post(STIX_URI + "/process-bundle") + .contentType(MediaType.APPLICATION_JSON) + .content("") + .with(csrf()); if (authHeader != null) { request = request.header("Authorization", authHeader); From 2012306ad5b7f239b043350310a61ed97ff45dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Wed, 25 Feb 2026 00:41:28 +0100 Subject: [PATCH 08/20] [backend] fix(csrf): tests (#1785) --- .../InjectorContratApiTest.java | 28 ++++++---- .../CustomDashboardApiTest.java | 14 ++--- ...xerciseApiImportWithExistingItemsTest.java | 52 +++++++++++++------ 3 files changed, 62 insertions(+), 32 deletions(-) diff --git a/openaev-api/src/test/java/io/openaev/injector_contract/InjectorContratApiTest.java b/openaev-api/src/test/java/io/openaev/injector_contract/InjectorContratApiTest.java index 4661805bd8b..bba2fe08de2 100644 --- a/openaev-api/src/test/java/io/openaev/injector_contract/InjectorContratApiTest.java +++ b/openaev-api/src/test/java/io/openaev/injector_contract/InjectorContratApiTest.java @@ -4,6 +4,7 @@ import static io.openaev.database.model.Filters.FilterOperator.eq; import static io.openaev.utils.JsonTestUtils.asJsonString; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -61,7 +62,8 @@ void given_search_input_should_return_a_page_of_contrats() throws Exception { mvc.perform( post("/api/injector_contracts/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(PaginationFixture.getDefault().build()))) + .content(asJsonString(PaginationFixture.getDefault().build())) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(5)); } @@ -75,7 +77,8 @@ void given_a_bad_search_input_should_throw_bad_request() throws Exception { mvc.perform( post("/api/injector_contracts/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().isBadRequest()); } } @@ -94,7 +97,8 @@ void given_search_input_with_textsearch_should_return_a_page_of_contrats_ignorin mvc.perform( post("/api/injector_contracts/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -109,7 +113,8 @@ void given_search_input_with_textsearch_with_spaces_should_return_a_page_of_cont mvc.perform( post("/api/injector_contracts/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(0)); } @@ -131,7 +136,8 @@ void given_search_input_with_label_type_should_return_a_page_of_contrats_ignorin mvc.perform( post("/api/injector_contracts/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -146,7 +152,8 @@ void given_search_input_with_label_should_return_a_page_of_contrats() throws Exc mvc.perform( post("/api/injector_contracts/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -162,7 +169,8 @@ void given_search_input_with_label_should_return_a_page_of_contrats_ignoring_cas mvc.perform( post("/api/injector_contracts/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.numberOfElements").value(1)); } @@ -189,7 +197,8 @@ void given_sort_input_should_return_a_page_of_contrats_sort_by_label_desc() thro mvc.perform( post("/api/injector_contracts/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect( jsonPath("$.content.[0].injector_contract_labels.en") @@ -216,7 +225,8 @@ void given_sort_input_should_return_a_page_of_contrats_sort_by_label_asc() throw mvc.perform( post("/api/injector_contracts/search") .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(searchPaginationInput))) + .content(asJsonString(searchPaginationInput)) + .with(csrf())) .andExpect(status().is2xxSuccessful()) .andExpect( jsonPath("$.content.[0].injector_contract_labels.en") diff --git a/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardApiTest.java b/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardApiTest.java index b7cf093b5b3..6208a9047c2 100644 --- a/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/custom_dashboard/CustomDashboardApiTest.java @@ -57,7 +57,8 @@ void given_valid_dashboard_input_when_creating_dashboard_should_return_created_d .perform( post(CUSTOM_DASHBOARDS_URI) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(input))) + .content(asJsonString(input)) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.custom_dashboard_name").value(name)); @@ -72,7 +73,7 @@ void given_dashboards_should_return_all_dashboards() throws Exception { // -- EXECUTE & ASSERT -- mockMvc - .perform(get(CUSTOM_DASHBOARDS_URI)) + .perform(get(CUSTOM_DASHBOARDS_URI).with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.length()").value(1)) .andExpect(jsonPath("$[0].custom_dashboard_name").value(NAME)); @@ -86,7 +87,7 @@ void given_dashboard_id_when_fetching_dashboard_should_return_dashboard() throws // -- EXECUTE & ASSERT -- mockMvc - .perform(get(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId())) + .perform(get(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId()).with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.custom_dashboard_name").value(NAME)); } @@ -106,7 +107,8 @@ void given_updated_dashboard_input_when_updating_dashboard_should_return_updated .perform( put(CUSTOM_DASHBOARDS_URI + "/" + customDashboard.getId()) .contentType(MediaType.APPLICATION_JSON) - .content(asJsonString(customDashboard))) + .content(asJsonString(customDashboard)) + .with(csrf())) .andExpect(status().isOk()) .andExpect(jsonPath("$.custom_dashboard_name").value(NAME)) .andExpect(jsonPath("$.custom_dashboard_description").value(customDashboardDescription)); @@ -127,7 +129,7 @@ void given_dashboard_id_when_deleting_dashboard_should_return_no_content() throw // -- EXECUTE & ASSERT -- mockMvc - .perform(delete(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId())) + .perform(delete(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId()).with(csrf())) .andExpect(status().isNoContent()); assertThat(repository.existsById(wrapper.get().getId())).isFalse(); @@ -150,7 +152,7 @@ void given_default_home_dashboard_id_when_deleting_should_throw_error() throws E settingRepository.save(defaultDashboardSetting); mockMvc - .perform(delete(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId())) + .perform(delete(CUSTOM_DASHBOARDS_URI + "/" + wrapper.get().getId()).with(csrf())) .andExpect(status().isBadRequest()) .andExpect( result -> { diff --git a/openaev-api/src/test/java/io/openaev/rest/exercise/imports/ExerciseApiImportWithExistingItemsTest.java b/openaev-api/src/test/java/io/openaev/rest/exercise/imports/ExerciseApiImportWithExistingItemsTest.java index 9a5d649e1f0..b632e93db4c 100644 --- a/openaev-api/src/test/java/io/openaev/rest/exercise/imports/ExerciseApiImportWithExistingItemsTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/exercise/imports/ExerciseApiImportWithExistingItemsTest.java @@ -3,6 +3,7 @@ import static io.openaev.rest.exercise.ExerciseApi.EXERCISE_URI; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -186,7 +187,8 @@ private byte[] doExport(ExerciseComposer.Composer composer) throws Exception { mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -217,7 +219,8 @@ private byte[] doExport(ExerciseComposer.Composer composer) throws Exception { mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -250,7 +253,8 @@ private byte[] doExport(ExerciseComposer.Composer composer) throws Exception { mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -288,7 +292,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_arti mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -337,7 +342,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_arti mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -369,7 +375,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_arti mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -405,7 +412,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_arti mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -437,7 +445,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_obje mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -485,7 +494,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_obje mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -518,7 +528,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_obje mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -567,7 +578,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_obje mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -599,7 +611,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_obje mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -629,7 +642,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_inje mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -680,7 +694,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_inje mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -710,7 +725,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_vari mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -758,7 +774,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_vari mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations @@ -790,7 +807,8 @@ public void given_a_valid_export_zip_file_given_existing_objects_create_new_vari mvc.perform( multipart(EXERCISE_URI + "/import") .file(mmf) - .contentType(MediaType.MULTIPART_FORM_DATA)) + .contentType(MediaType.MULTIPART_FORM_DATA) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // force hibernate to clear its cache to not pollute fetch operations From 477a8445801723a834df271c37364ddf6acc07f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Tue, 24 Mar 2026 14:30:19 +0100 Subject: [PATCH 09/20] [backend] feat(csrf): try to open all technical routes (#1785) --- .../io/openaev/config/AppSecurityConfig.java | 6 ++++ .../openaev/api/stix_process/StixApiTest.java | 29 +++++++++---------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java index e8efe197ee9..398ee3905fa 100644 --- a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java +++ b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java @@ -78,6 +78,12 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/api/agent/**", "/api/implant/**", "/api/reset/**", + "/api/endpoints/register", + "/api/endpoints/jobs/**", + "/api/injects/execution/**", + "/api/stix/**", + "/api/xtm-composer/**", + "/api/xtmhub/**", "/actuator/**")) .formLogin(AbstractHttpConfigurer::disable) .securityContext(securityContext -> securityContext.requireExplicitSave(false)) diff --git a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java index 57e62f55435..8dc1c60e448 100644 --- a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java +++ b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java @@ -14,7 +14,6 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; -import static org.mockserver.model.HttpResponse.response; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -327,7 +326,7 @@ void shouldReturn200OKWhenNoSecurityCoverage() throws Exception { post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) .content(mapper.writeValueAsString(updated))) - .andExpect(status().isBadRequest()); + .andExpect(status().isOk()); } @Test @@ -339,8 +338,8 @@ void shouldReturn200OKWhenMultipleSecurityCoverages() throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(duplicatedCoverage)) - .andExpect(status().isBadRequest()); + .content(content)) + .andExpect(status().isOk()); } @Test @@ -348,10 +347,10 @@ void shouldReturn200OKWhenMultipleSecurityCoverages() throws Exception { void shouldReturnBadRequestWhenStixJsonIsInvalid() throws Exception { String invalidJson = """ - { - "not-a-valid-json": - } - """; + { + "not-a-valid-json": + } + """; mvc.perform( post(STIX_URI + "/process-bundle") @@ -365,11 +364,11 @@ void shouldReturnBadRequestWhenStixJsonIsInvalid() throws Exception { void shouldReturnBadRequestWhenStixStructureInvalid() throws Exception { String structurallyInvalidStix = """ - { - "type": "bundle", - "id": "bundle--1234" - } - """; + { + "type": "bundle", + "id": "bundle--1234" + } + """; mvc.perform( post(STIX_URI + "/process-bundle") @@ -423,7 +422,7 @@ void shouldReturn200OKEvenWhenSecurityCoverageIsAlreadySaved() throws Exception post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) .content(mapper.writeValueAsString(stixSecurityCoverage))) - .andExpect(status().isBadRequest()); + .andExpect(status().isOk()); } @Test @@ -460,7 +459,7 @@ void shouldReturn200OKEvenWhenSecurityCoverageIsObsolete() throws Exception { post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) .content(mapper.writeValueAsString(updated))) - .andExpect(status().isBadRequest()); + .andExpect(status().isOk()); } @Test From 929eaa7fff69c27542be658fee92d713c71c20f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Tue, 24 Mar 2026 14:32:47 +0100 Subject: [PATCH 10/20] [backend] feat(csrf): try to open all technical routes (#1785) --- .../openaev/api/stix_process/StixApiTest.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java index 8dc1c60e448..f490eb173aa 100644 --- a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java +++ b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java @@ -347,10 +347,10 @@ void shouldReturn200OKWhenMultipleSecurityCoverages() throws Exception { void shouldReturnBadRequestWhenStixJsonIsInvalid() throws Exception { String invalidJson = """ - { - "not-a-valid-json": - } - """; + { + "not-a-valid-json": + } + """; mvc.perform( post(STIX_URI + "/process-bundle") @@ -364,11 +364,11 @@ void shouldReturnBadRequestWhenStixJsonIsInvalid() throws Exception { void shouldReturnBadRequestWhenStixStructureInvalid() throws Exception { String structurallyInvalidStix = """ - { - "type": "bundle", - "id": "bundle--1234" - } - """; + { + "type": "bundle", + "id": "bundle--1234" + } + """; mvc.perform( post(STIX_URI + "/process-bundle") From aed2886d57cc8e87bc2567c232f9c2d1e4528b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Tue, 24 Mar 2026 14:48:49 +0100 Subject: [PATCH 11/20] [backend] feat(csrf): add connector-instance ignoring matcher (#1785) --- .../src/main/java/io/openaev/config/AppSecurityConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java index 398ee3905fa..ad3461bb928 100644 --- a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java +++ b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java @@ -84,6 +84,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/api/stix/**", "/api/xtm-composer/**", "/api/xtmhub/**", + "/api/connector-instances/**", "/actuator/**")) .formLogin(AbstractHttpConfigurer::disable) .securityContext(securityContext -> securityContext.requireExplicitSave(false)) From 5ef190bb326fa43a31bec94d195ae586134f083b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Tue, 24 Mar 2026 15:15:08 +0100 Subject: [PATCH 12/20] [backend] feat(csrf): review tests (#1785) --- .../io/openaev/config/AppSecurityConfig.java | 2 ++ .../api/payload/PayloadApiImporterTest.java | 26 +++++++++++++++---- .../openaev/api/stix_process/StixApiTest.java | 4 ++- .../rest/exercise/ExerciseApiTest.java | 6 +++-- .../rest/scenario/ScenarioTeamApiTest.java | 6 +++-- 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java index ad3461bb928..518aee9b6fd 100644 --- a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java +++ b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java @@ -85,6 +85,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/api/xtm-composer/**", "/api/xtmhub/**", "/api/connector-instances/**", + "/api/injectors/**", + "/api/collectors/**", "/actuator/**")) .formLogin(AbstractHttpConfigurer::disable) .securityContext(securityContext -> securityContext.requireExplicitSave(false)) diff --git a/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java b/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java index 96940f6b57c..4fc25dfb695 100644 --- a/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java +++ b/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java @@ -113,7 +113,13 @@ void importPayloadReturnsPayloadWithAllArrayFields() throws Exception { MockMultipartFile zipFile = buildZipFile(document); // -- EXECUTE -- - String response = performImport(zipFile); + String response = + mockMvc + .perform(multipart(PAYLOAD_URI + "/import").file(zipFile)) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse() + .getContentAsString(); // -- ASSERT -- assertNotNull(response); @@ -157,8 +163,13 @@ void importPayloadWithEmptyArrayFields() throws Exception { MockMultipartFile zipFile = buildZipFile(document); - // -- EXECUTE -- - String response = performImport(zipFile); + String response = + mockMvc + .perform(multipart(PAYLOAD_URI + "/import").file(zipFile)) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse() + .getContentAsString(); // -- ASSERT -- assertNotNull(response); @@ -427,8 +438,13 @@ void importPayloadWithNullArrayFields() throws Exception { MockMultipartFile zipFile = buildZipFile(document); - // -- EXECUTE -- - String response = performImport(zipFile); + String response = + mockMvc + .perform(multipart(PAYLOAD_URI + "/import").file(zipFile)) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse() + .getContentAsString(); // -- ASSERT -- assertNotNull(response); diff --git a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java index f490eb173aa..9a043571b3d 100644 --- a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java +++ b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java @@ -14,6 +14,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -951,7 +952,8 @@ void shouldExistSecurityCoverage() throws Exception { void shouldNotDuplicatedReferenceSecurityCoverage() throws Exception { String scenarioId = getScenarioIdResponse(mapper.writeValueAsString(stixSecurityCoverage)); String duplicated = - mvc.perform(post(SCENARIO_URI + "/" + scenarioId).contentType(MediaType.APPLICATION_JSON)) + mvc.perform(post(SCENARIO_URI + "/" + scenarioId).contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiTest.java b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiTest.java index dd550090357..fd309bd0558 100644 --- a/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/exercise/ExerciseApiTest.java @@ -513,7 +513,8 @@ void deselectedTeamShouldRemoveLinksOnlyForCurrentExercise() throws Exception { put(EXERCISE_URI + "/" + exerciseASaved.getId() + "/teams/replace") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(input)) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()); // -- ASSERT -- @@ -569,7 +570,8 @@ void replacingTeamsShouldPersistNewTeamListInDatabase() throws Exception { put(EXERCISE_URI + "/" + exerciseSaved.getId() + "/teams/replace") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(input)) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()); // -- ASSERT -- diff --git a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java index c432d418cfd..dc5e5d5c093 100644 --- a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java @@ -462,14 +462,16 @@ void callingReplaceTeamsTwiceShouldNotCauseDuplicateKey() throws Exception { put(SCENARIO_URI + "/" + scenarioSaved.getId() + "/teams/replace") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); mvc.perform( put(SCENARIO_URI + "/" + scenarioSaved.getId() + "/teams/replace") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // -- ASSERT -- From e8ffb51993b259d6876d4f04acae077287816fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Tue, 24 Mar 2026 15:20:14 +0100 Subject: [PATCH 13/20] [backend] feat(csrf): spotless (#1785) --- .../test/java/io/openaev/api/stix_process/StixApiTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java index 9a043571b3d..0a95088d617 100644 --- a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java +++ b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java @@ -952,8 +952,10 @@ void shouldExistSecurityCoverage() throws Exception { void shouldNotDuplicatedReferenceSecurityCoverage() throws Exception { String scenarioId = getScenarioIdResponse(mapper.writeValueAsString(stixSecurityCoverage)); String duplicated = - mvc.perform(post(SCENARIO_URI + "/" + scenarioId).contentType(MediaType.APPLICATION_JSON) - .with(csrf())) + mvc.perform( + post(SCENARIO_URI + "/" + scenarioId) + .contentType(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() From 0efe22ef83f1705d2e358bd4827fb458388d3480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Tue, 24 Mar 2026 15:30:38 +0100 Subject: [PATCH 14/20] [backend] feat(csrf): review tests (#1785) --- .../java/io/openaev/rest/scenario/ScenarioTeamApiTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java index dc5e5d5c093..4178672df65 100644 --- a/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/scenario/ScenarioTeamApiTest.java @@ -409,7 +409,8 @@ void deselectedTeamShouldRemoveLinksOnlyForCurrentScenario() throws Exception { put(SCENARIO_URI + "/" + scenarioASaved.getId() + "/teams/replace") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // -- ASSERT -- @@ -513,7 +514,8 @@ void replacingTeamsShouldPersistNewTeamListInDatabase() throws Exception { put(SCENARIO_URI + "/" + scenarioSaved.getId() + "/teams/replace") .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); // -- ASSERT -- From 21d50ea7c899ad598d1ffe06f274de33fd5eb15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Wed, 25 Mar 2026 15:28:41 +0100 Subject: [PATCH 15/20] [backend] fix(csrf): start to review url used by technical processes (#1785) --- .../io/openaev/config/AppSecurityConfig.java | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java index 518aee9b6fd..0daa6e7858e 100644 --- a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java +++ b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java @@ -75,19 +75,33 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/api/comcheck/**", "/api/player/**", "/api/settings", + "/api/reset/**", + "/actuator/**", + // Used by endpoints + "/api/endpoints/**", "/api/agent/**", + // Used by implants "/api/implant/**", - "/api/reset/**", - "/api/endpoints/register", - "/api/endpoints/jobs/**", "/api/injects/execution/**", - "/api/stix/**", - "/api/xtm-composer/**", - "/api/xtmhub/**", - "/api/connector-instances/**", + // Used by injectors to register contracts "/api/injectors/**", + "/api/injector_contracts/**", + // Used by collectors, "/api/collectors/**", - "/actuator/**")) + "/api/documents/**", + "/api/cves/**", + "/api/attack_patterns/**", + "/api/payloads/**", + "/api/tags/**", + "/api/kill_chain_phases/**", + // Used by connectors + "/api/connector-instances/**", + // XTM Hub + "/api/xtmhub/**", + // XTM Composer + "/api/xtm-composer/**", + // OpenCTI interconnection + "/api/stix/**")) .formLogin(AbstractHttpConfigurer::disable) .securityContext(securityContext -> securityContext.requireExplicitSave(false)) .authorizeHttpRequests( From 36c945488b34095e878b3e80338d3d28af95dfa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Wed, 25 Mar 2026 17:49:23 +0100 Subject: [PATCH 16/20] [backend] fix(csrf): add injectors urls (#1785) --- .../src/main/java/io/openaev/config/AppSecurityConfig.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java index 0daa6e7858e..0c08820235f 100644 --- a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java +++ b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java @@ -82,8 +82,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/api/agent/**", // Used by implants "/api/implant/**", - "/api/injects/execution/**", - // Used by injectors to register contracts + "/api/injects/**", + // Used by injectors "/api/injectors/**", "/api/injector_contracts/**", // Used by collectors, @@ -94,6 +94,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/api/payloads/**", "/api/tags/**", "/api/kill_chain_phases/**", + "/api/security_platforms/**", + "/api/inject-expectations-traces/**", // Used by connectors "/api/connector-instances/**", // XTM Hub From 15f0cf0dcfe965ed1660345b113173b8b262f085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Fri, 10 Apr 2026 08:57:29 +0200 Subject: [PATCH 17/20] [frontend/backend] fix(csrf): try to fix issue (#1785) --- .../io/openaev/config/AppSecurityConfig.java | 49 +++----- .../api/payload/PayloadApiImporterTest.java | 106 +++++++++++++----- openaev-front/src/network.ts | 27 ++++- 3 files changed, 116 insertions(+), 66 deletions(-) diff --git a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java index 0c08820235f..6e481662d74 100644 --- a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java +++ b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java @@ -14,6 +14,7 @@ import io.openaev.service.UserMappingService; import io.openaev.service.user_events.UserEventService; import jakarta.annotation.Resource; +import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import java.util.List; import lombok.RequiredArgsConstructor; @@ -21,6 +22,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -45,6 +47,7 @@ import org.springframework.security.web.csrf.CookieCsrfTokenRepository; import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.util.matcher.RequestMatcher; @Configuration @EnableWebSecurity @@ -70,40 +73,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()) .ignoringRequestMatchers( - "/api/health", - "/api/login", - "/api/comcheck/**", - "/api/player/**", - "/api/settings", - "/api/reset/**", - "/actuator/**", - // Used by endpoints - "/api/endpoints/**", - "/api/agent/**", - // Used by implants - "/api/implant/**", - "/api/injects/**", - // Used by injectors - "/api/injectors/**", - "/api/injector_contracts/**", - // Used by collectors, - "/api/collectors/**", - "/api/documents/**", - "/api/cves/**", - "/api/attack_patterns/**", - "/api/payloads/**", - "/api/tags/**", - "/api/kill_chain_phases/**", - "/api/security_platforms/**", - "/api/inject-expectations-traces/**", - // Used by connectors - "/api/connector-instances/**", - // XTM Hub - "/api/xtmhub/**", - // XTM Composer - "/api/xtm-composer/**", - // OpenCTI interconnection - "/api/stix/**")) + "/api/health", "/api/login", "/actuator/**") + .ignoringRequestMatchers(bearerWithoutCookiesMatcher())) .formLogin(AbstractHttpConfigurer::disable) .securityContext(securityContext -> securityContext.requireExplicitSave(false)) .authorizeHttpRequests( @@ -267,4 +238,14 @@ private OAuth2AuthorizationRequest customize( } }; } + + private RequestMatcher bearerWithoutCookiesMatcher() { + return request -> { + String authorization = request.getHeader(HttpHeaders.AUTHORIZATION); + Cookie[] cookies = request.getCookies(); + boolean hasBearer = authorization != null && authorization.startsWith("Bearer "); + boolean hasCookies = cookies != null && cookies.length > 0; + return hasBearer && !hasCookies; + }; + } } diff --git a/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java b/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java index 4fc25dfb695..9ccbb44b45c 100644 --- a/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java +++ b/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java @@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -68,14 +69,79 @@ private MockMultipartFile buildZipFile(JsonApiDocument document) return new MockMultipartFile("file", "payload.zip", "application/zip", zip); } + private String performImport(MockMultipartFile zipFile) throws Exception { + return mockMvc + .perform(multipart(PAYLOAD_URI + "/import").file(zipFile)) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse() + .getContentAsString(); + } + + // -- TESTS -- + + @Test + @DisplayName("Import payload should create injector contract") + void importPayloadShouldCreateInjectorContract() throws Exception { + new Manager(List.of(openaevInjectorIntegrationFactory)).monitorIntegrations(); + + // -- PREPARE -- + String domainId = "02e33774-33ae-4d65-91fd-a9c0e1a37c7b"; + Map domainAttributes = new HashMap<>(); + domainAttributes.put("domain_id", domainId); + domainAttributes.put("domain_name", "Data Exfiltration"); + domainAttributes.put("domain_color", "#9933CC"); + domainAttributes.put("domain_created_at", "2026-02-02T14:55:27.442379Z"); + domainAttributes.put("domain_updated_at", "2026-02-02T14:55:27.442379Z"); + ResourceObject domainElement = + new ResourceObject(domainId, "domains", domainAttributes, emptyMap()); + + JsonApiDocument document = + new JsonApiDocument<>( + new ResourceObject( + null, + "command", + buildDefaultPayloadAttributes(), + Map.of( + "payload_domains", + new Relationship(List.of(new ResourceIdentifier(domainId, "domains"))))), + List.of(domainElement)); + + MockMultipartFile zipFile = buildZipFile(document); + + // -- EXECUTE -- + String response = performImport(zipFile); + + // -- ASSERT -- + assertNotNull(response); + + JsonNode json = objectMapper.readTree(response); + String payloadId = json.at("/data/attributes/payload_id").asText(); + assertNotNull(payloadId); + + Optional payloadPersisted = payloadRepository.findById(payloadId); + assertFalse(payloadPersisted.isEmpty(), "Payload should have been persisted in the database"); + + List injectorContracts = + injectorContractRepository.findInjectorContractsByPayload(payloadPersisted.get()); + assertNotNull(injectorContracts); + assertEquals(1, injectorContracts.size()); + assertEquals(payloadId, injectorContracts.getFirst().getPayload().getId()); + } + + @Test + @DisplayName("Import a payload returns complete entity") + void importPayloadReturnsPayloadWithRelationship() throws Exception { + // -- PREPARE -- + JsonApiDocument document = + new JsonApiDocument<>( + new ResourceObject(null, "command", buildDefaultPayloadAttributes(), emptyMap()), + emptyList()); + + MockMultipartFile zipFile = buildZipFile(document); + // -- EXECUTE -- - String response = - mockMvc - .perform(multipart(PAYLOAD_URI + "/import").file(zipFile)) - .andExpect(status().is2xxSuccessful()) - .andReturn() - .getResponse() - .getContentAsString(); + String response = performImport(zipFile); // -- ASSERT -- assertNotNull(response); @@ -113,13 +179,7 @@ void importPayloadReturnsPayloadWithAllArrayFields() throws Exception { MockMultipartFile zipFile = buildZipFile(document); // -- EXECUTE -- - String response = - mockMvc - .perform(multipart(PAYLOAD_URI + "/import").file(zipFile)) - .andExpect(status().is2xxSuccessful()) - .andReturn() - .getResponse() - .getContentAsString(); + String response = performImport(zipFile); // -- ASSERT -- assertNotNull(response); @@ -163,13 +223,8 @@ void importPayloadWithEmptyArrayFields() throws Exception { MockMultipartFile zipFile = buildZipFile(document); - String response = - mockMvc - .perform(multipart(PAYLOAD_URI + "/import").file(zipFile)) - .andExpect(status().is2xxSuccessful()) - .andReturn() - .getResponse() - .getContentAsString(); + // -- EXECUTE -- + String response = performImport(zipFile); // -- ASSERT -- assertNotNull(response); @@ -438,13 +493,8 @@ void importPayloadWithNullArrayFields() throws Exception { MockMultipartFile zipFile = buildZipFile(document); - String response = - mockMvc - .perform(multipart(PAYLOAD_URI + "/import").file(zipFile)) - .andExpect(status().is2xxSuccessful()) - .andReturn() - .getResponse() - .getContentAsString(); + // -- EXECUTE -- + String response = performImport(zipFile); // -- ASSERT -- assertNotNull(response); diff --git a/openaev-front/src/network.ts b/openaev-front/src/network.ts index d113293fbce..26532da1ef2 100644 --- a/openaev-front/src/network.ts +++ b/openaev-front/src/network.ts @@ -11,6 +11,24 @@ interface ApiErrorResponse { [key: string]: unknown; } +let csrfBootstrapPromise: Promise | null = null; + +const hasCsrfCookie = (): boolean => + document.cookie.split('; ').some((row) => row.startsWith('XSRF-TOKEN=')); + +const ensureCsrfCookie = async (instance: AxiosInstance): Promise => { + if (hasCsrfCookie()) return; + + csrfBootstrapPromise ??= instance + .get('/csrf') + .then(() => undefined) + .finally(() => { + csrfBootstrapPromise = null; + }); + + await csrfBootstrapPromise; +}; + // eslint-disable-next-line import/prefer-default-export export const api = (schema?: Schema | null): AxiosInstance => { const instance = axios.create({ @@ -19,11 +37,13 @@ export const api = (schema?: Schema | null): AxiosInstance => { }); // Intercept REQUEST to inject CSRF token - instance.interceptors.request.use((config) => { + instance.interceptors.request.use(async (config) => { const method = (config.method ?? 'GET').toUpperCase(); const mutating = ['POST', 'PUT', 'DELETE', 'PATCH'].includes(method); if (mutating) { + await ensureCsrfCookie(instance); + const match = document.cookie .split('; ') .find(row => row.startsWith('XSRF-TOKEN=')); @@ -52,7 +72,7 @@ export const api = (schema?: Schema | null): AxiosInstance => { // Automatic retry on 403 if XSRF cookie have just been dropped // eslint-disable-next-line no-underscore-dangle - if (res && res.status === 403 && config && !config.__isRetryRequest) { + if (res?.status === 403 && config && !config.__isRetryRequest) { const csrfCookie = document.cookie .split('; ') .find(row => row.startsWith('XSRF-TOKEN=')); @@ -65,8 +85,7 @@ export const api = (schema?: Schema | null): AxiosInstance => { } if ( - res - && res.status === 503 + res?.status === 503 && config // eslint-disable-next-line no-underscore-dangle && !config.__isRetryRequest From f20524118a2512cb9f2378cebd47088e9d02ae75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Mon, 13 Apr 2026 17:58:25 +0200 Subject: [PATCH 18/20] [backend] feat(csrf): review complete csrf process (#1785) --- .../io/openaev/config/AppSecurityConfig.java | 3 +- .../openaev/config/AppSecurityConfigTest.java | 165 ++++++++++++++++++ 2 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 openaev-api/src/test/java/io/openaev/config/AppSecurityConfigTest.java diff --git a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java index 6e481662d74..6d49b27e372 100644 --- a/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java +++ b/openaev-api/src/main/java/io/openaev/config/AppSecurityConfig.java @@ -72,8 +72,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()) - .ignoringRequestMatchers( - "/api/health", "/api/login", "/actuator/**") + .ignoringRequestMatchers("/api/health", "/api/login", "/actuator/**") .ignoringRequestMatchers(bearerWithoutCookiesMatcher())) .formLogin(AbstractHttpConfigurer::disable) .securityContext(securityContext -> securityContext.requireExplicitSave(false)) diff --git a/openaev-api/src/test/java/io/openaev/config/AppSecurityConfigTest.java b/openaev-api/src/test/java/io/openaev/config/AppSecurityConfigTest.java new file mode 100644 index 00000000000..87d86305a66 --- /dev/null +++ b/openaev-api/src/test/java/io/openaev/config/AppSecurityConfigTest.java @@ -0,0 +1,165 @@ +package io.openaev.config; + +import static io.openaev.rest.scenario.ScenarioApi.SCENARIO_URI; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import io.openaev.IntegrationTest; +import jakarta.servlet.http.Cookie; +import java.util.Objects; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +@TestInstance(Lifecycle.PER_CLASS) +@Transactional +@DisplayName("App Security Config tests") +public class AppSecurityConfigTest extends IntegrationTest { + + @Autowired private MockMvc mockMvc; + + @Value("${openbas.admin.token:${openaev.admin.token:#{null}}}") + private String adminToken; + + private static final String SCENARIO_SEARCH_URI = SCENARIO_URI + "/search"; + private static final String AUTH_COOKIE_NAME = "openaev_token"; + private static final String CSRF_COOKIE_NAME = "XSRF-TOKEN"; + private static final String CSRF_HEADER_NAME = "X-XSRF-TOKEN"; + private static final String SEARCH_BODY = + """ + { + "page": 0, + "size": 20, + "sorts": [] + } + """; + + @Test + @DisplayName("given valid admin bearer token without cookies, should return HTTP 200") + void given_validAdminBearerTokenWithoutCookies_should_returnOk() throws Exception { + mockMvc + .perform( + post(SCENARIO_SEARCH_URI) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + adminToken) + .contentType(MediaType.APPLICATION_JSON) + .content(SEARCH_BODY)) + .andExpect(status().isOk()); + } + + @Test + @DisplayName("given invalid bearer token, should return HTTP 401") + void given_invalidBearerToken_should_returnUnauthorized() throws Exception { + mockMvc + .perform( + post(SCENARIO_SEARCH_URI) + .header(HttpHeaders.AUTHORIZATION, "Bearer not-a-valid-token") + .contentType(MediaType.APPLICATION_JSON) + .content(SEARCH_BODY)) + .andExpect(status().isUnauthorized()); + } + + @Test + @DisplayName("given valid bearer token and non auth cookie, should return HTTP 403") + void given_validBearerTokenAndNonAuthCookie_should_returnForbidden() throws Exception { + Cookie trackingCookie = new Cookie("tracking_id", "abc"); + + mockMvc + .perform( + post(SCENARIO_SEARCH_URI) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + adminToken) + .cookie(trackingCookie) + .contentType(MediaType.APPLICATION_JSON) + .content(SEARCH_BODY)) + .andExpect(status().isForbidden()); + } + + @Test + @DisplayName("given valid auth cookie and csrf without bearer token, should return HTTP 200") + void given_validAuthCookieAndCsrfWithoutBearerToken_should_returnOk() throws Exception { + Cookie authCookie = new Cookie(AUTH_COOKIE_NAME, adminToken); + Cookie csrfCookie = new Cookie(CSRF_COOKIE_NAME, "test-csrf-token"); + + mockMvc + .perform( + post(SCENARIO_SEARCH_URI) + .cookie(authCookie, csrfCookie) + .header(CSRF_HEADER_NAME, "test-csrf-token") + .contentType(MediaType.APPLICATION_JSON) + .content(SEARCH_BODY)) + .andExpect(status().isOk()); + } + + @Test + @DisplayName( + "given valid auth cookie and invalid csrf without bearer token, should return HTTP 403") + void given_validAuthCookieAndInvalidCsrfWithoutBearerToken_should_returnUnauthorized() + throws Exception { + Cookie authCookie = new Cookie(AUTH_COOKIE_NAME, adminToken); + Cookie csrfCookie = new Cookie(CSRF_COOKIE_NAME, "test-csrf-token-broken"); + + mockMvc + .perform( + post(SCENARIO_SEARCH_URI) + .cookie(authCookie, csrfCookie) + .header(CSRF_HEADER_NAME, "test-csrf-token") + .contentType(MediaType.APPLICATION_JSON) + .content(SEARCH_BODY)) + .andExpect(status().isForbidden()); + } + + @Test + @DisplayName("given jsessionid cookie and csrf without bearer token, should return HTTP 401") + void given_jsessionIdCookieAndCsrfWithoutBearerToken_should_returnUnauthorized() + throws Exception { + Cookie jsessionCookie = new Cookie("JSESSIONID", "dummy-session-id"); + Cookie csrfCookie = new Cookie(CSRF_COOKIE_NAME, "test-csrf-token"); + + mockMvc + .perform( + post(SCENARIO_SEARCH_URI) + .cookie(jsessionCookie, csrfCookie) + .header(CSRF_HEADER_NAME, "test-csrf-token") + .contentType(MediaType.APPLICATION_JSON) + .content(SEARCH_BODY)) + .andExpect(status().isUnauthorized()); + } + + @Test + @DisplayName("given valid jsessionid and csrf without bearer token, should return HTTP 200") + void given_validJsessionIdAndCsrfWithoutBearerToken_should_returnOk() throws Exception { + MockHttpSession session = new MockHttpSession(); + Cookie csrfCookie = new Cookie(CSRF_COOKIE_NAME, "test-csrf-token"); + mockMvc + .perform( + post(SCENARIO_SEARCH_URI) + .session(session) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + adminToken) + .cookie(csrfCookie) + .header(CSRF_HEADER_NAME, "test-csrf-token") + .contentType(MediaType.APPLICATION_JSON) + .content(SEARCH_BODY)) + .andExpect(status().isOk()); + + String sessionId = Objects.requireNonNull(session.getId()); + Cookie jsessionCookie = new Cookie("JSESSIONID", sessionId); + + mockMvc + .perform( + post(SCENARIO_SEARCH_URI) + .session(session) + .cookie(jsessionCookie) + .cookie(new Cookie(CSRF_COOKIE_NAME, "test-csrf-token")) + .header(CSRF_HEADER_NAME, "test-csrf-token") + .contentType(MediaType.APPLICATION_JSON) + .content(SEARCH_BODY)) + .andExpect(status().isOk()); + } +} From 4fa610b8622a9ec19f92bd68612eafc2ebcc7bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Mon, 13 Apr 2026 18:19:20 +0200 Subject: [PATCH 19/20] [frontend/backend] feat(security): lint and spotless (#1785) --- .../openaev/api/stix_process/StixApiTest.java | 42 ++++++++++++------- .../rest/ConnectorInstanceApiTest.java | 9 ++-- openaev-front/src/network.ts | 2 +- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java index 0a95088d617..c4bb42e00fa 100644 --- a/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java +++ b/openaev-api/src/test/java/io/openaev/api/stix_process/StixApiTest.java @@ -51,7 +51,6 @@ import java.util.*; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.*; -import org.mockserver.integration.ClientAndServer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.http.MediaType; @@ -104,8 +103,6 @@ class StixApiTest extends IntegrationTest { private JsonNode stixSecurityCoverageOnlyVulns; private JsonNode stixSecurityCoverageWithDomainName; - private static ClientAndServer mockServer; - @BeforeEach void setUp() throws Exception { @@ -220,7 +217,8 @@ class ImportStixBundles { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(stixSecurityCoverageNoPlatformAffinity))) + .content(mapper.writeValueAsString(stixSecurityCoverageNoPlatformAffinity)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -280,7 +278,8 @@ void eligibleAssetGroupsAreAssignedByTagRule() throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(updated))) + .content(mapper.writeValueAsString(updated)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -326,7 +325,8 @@ void shouldReturn200OKWhenNoSecurityCoverage() throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(updated))) + .content(mapper.writeValueAsString(updated)) + .with(csrf())) .andExpect(status().isOk()); } @@ -339,7 +339,8 @@ void shouldReturn200OKWhenMultipleSecurityCoverages() throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(content)) + .content(content) + .with(csrf())) .andExpect(status().isOk()); } @@ -356,7 +357,8 @@ void shouldReturnBadRequestWhenStixJsonIsInvalid() throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(invalidJson)) + .content(invalidJson) + .with(csrf())) .andExpect(status().isBadRequest()); } @@ -374,7 +376,8 @@ void shouldReturnBadRequestWhenStixStructureInvalid() throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(structurallyInvalidStix)) + .content(structurallyInvalidStix) + .with(csrf())) .andExpect(status().isBadRequest()); } @@ -387,7 +390,8 @@ void shouldCreateScenarioNoEnd() throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(stixSecurityCoverageNoDuration))) + .content(mapper.writeValueAsString(stixSecurityCoverageNoDuration)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -413,7 +417,8 @@ void shouldReturn200OKEvenWhenSecurityCoverageIsAlreadySaved() throws Exception mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(stixSecurityCoverage))) + .content(mapper.writeValueAsString(stixSecurityCoverage)) + .with(csrf())) .andExpect(status().isOk()); entityManager.flush(); @@ -422,7 +427,8 @@ void shouldReturn200OKEvenWhenSecurityCoverageIsAlreadySaved() throws Exception mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(stixSecurityCoverage))) + .content(mapper.writeValueAsString(stixSecurityCoverage)) + .with(csrf())) .andExpect(status().isOk()); } @@ -441,7 +447,8 @@ void shouldReturn200OKEvenWhenSecurityCoverageIsObsolete() throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(referenceInput))) + .content(mapper.writeValueAsString(referenceInput)) + .with(csrf())) .andExpect(status().isOk()); entityManager.flush(); @@ -459,7 +466,8 @@ void shouldReturn200OKEvenWhenSecurityCoverageIsObsolete() throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(updated))) + .content(mapper.writeValueAsString(updated)) + .with(csrf())) .andExpect(status().isOk()); } @@ -973,7 +981,8 @@ void shouldCreateScenarioWithDomainNameResolutionInjects() throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(stixSecurityCoverageWithDomainName))) + .content(mapper.writeValueAsString(stixSecurityCoverageWithDomainName)) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -998,7 +1007,8 @@ private String getScenarioIdResponse(String content) throws Exception { mvc.perform( post(STIX_URI + "/process-bundle") .contentType(MediaType.APPLICATION_JSON) - .content(content)) + .content(content) + .with(csrf())) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/rest/ConnectorInstanceApiTest.java b/openaev-api/src/test/java/io/openaev/rest/ConnectorInstanceApiTest.java index 69237ca6e52..496663bfb46 100644 --- a/openaev-api/src/test/java/io/openaev/rest/ConnectorInstanceApiTest.java +++ b/openaev-api/src/test/java/io/openaev/rest/ConnectorInstanceApiTest.java @@ -231,7 +231,8 @@ void givenCollectorOfSameTypeAlreadyExists_should_throwError() throws Exception post(CONNECTOR_INSTANCE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()) .andExpect( result -> { @@ -295,7 +296,8 @@ void givenCollectorOfSameTypeAlreadyExists_should_successfullyMigrateWhenCollect post(CONNECTOR_INSTANCE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is2xxSuccessful()); List instanceDb = @@ -364,7 +366,8 @@ void givenCollectorIdNotMatchingAnyCollector_should_throwError() throws Exceptio post(CONNECTOR_INSTANCE_URI) .content(asJsonString(input)) .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON) + .with(csrf())) .andExpect(status().is4xxClientError()) .andExpect( result -> { diff --git a/openaev-front/src/network.ts b/openaev-front/src/network.ts index 26532da1ef2..66b513fed07 100644 --- a/openaev-front/src/network.ts +++ b/openaev-front/src/network.ts @@ -14,7 +14,7 @@ interface ApiErrorResponse { let csrfBootstrapPromise: Promise | null = null; const hasCsrfCookie = (): boolean => - document.cookie.split('; ').some((row) => row.startsWith('XSRF-TOKEN=')); + document.cookie.split('; ').some(row => row.startsWith('XSRF-TOKEN=')); const ensureCsrfCookie = async (instance: AxiosInstance): Promise => { if (hasCsrfCookie()) return; From a42e0e9af72109225d40199af817d4c1c5dabd30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20PEZ=C3=89?= Date: Mon, 13 Apr 2026 18:35:20 +0200 Subject: [PATCH 20/20] [frontend/backend] feat(security): spotless (#1785) --- .../openaev/api/payload/PayloadApiImporterTest.java | 3 ++- .../io/openaev/config/AppSecurityConfigTest.java | 13 +++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java b/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java index 9ccbb44b45c..c65bf6cb86e 100644 --- a/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java +++ b/openaev-api/src/test/java/io/openaev/api/payload/PayloadApiImporterTest.java @@ -8,6 +8,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -71,7 +72,7 @@ private MockMultipartFile buildZipFile(JsonApiDocument document) private String performImport(MockMultipartFile zipFile) throws Exception { return mockMvc - .perform(multipart(PAYLOAD_URI + "/import").file(zipFile)) + .perform(multipart(PAYLOAD_URI + "/import").file(zipFile).with(csrf())) .andExpect(status().is2xxSuccessful()) .andReturn() .getResponse() diff --git a/openaev-api/src/test/java/io/openaev/config/AppSecurityConfigTest.java b/openaev-api/src/test/java/io/openaev/config/AppSecurityConfigTest.java index 87d86305a66..44e5541d61f 100644 --- a/openaev-api/src/test/java/io/openaev/config/AppSecurityConfigTest.java +++ b/openaev-api/src/test/java/io/openaev/config/AppSecurityConfigTest.java @@ -1,6 +1,7 @@ package io.openaev.config; import static io.openaev.rest.scenario.ScenarioApi.SCENARIO_URI; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -93,7 +94,8 @@ void given_validAuthCookieAndCsrfWithoutBearerToken_should_returnOk() throws Exc .cookie(authCookie, csrfCookie) .header(CSRF_HEADER_NAME, "test-csrf-token") .contentType(MediaType.APPLICATION_JSON) - .content(SEARCH_BODY)) + .content(SEARCH_BODY) + .with(csrf())) .andExpect(status().isOk()); } @@ -128,7 +130,8 @@ void given_jsessionIdCookieAndCsrfWithoutBearerToken_should_returnUnauthorized() .cookie(jsessionCookie, csrfCookie) .header(CSRF_HEADER_NAME, "test-csrf-token") .contentType(MediaType.APPLICATION_JSON) - .content(SEARCH_BODY)) + .content(SEARCH_BODY) + .with(csrf())) .andExpect(status().isUnauthorized()); } @@ -145,7 +148,8 @@ void given_validJsessionIdAndCsrfWithoutBearerToken_should_returnOk() throws Exc .cookie(csrfCookie) .header(CSRF_HEADER_NAME, "test-csrf-token") .contentType(MediaType.APPLICATION_JSON) - .content(SEARCH_BODY)) + .content(SEARCH_BODY) + .with(csrf())) .andExpect(status().isOk()); String sessionId = Objects.requireNonNull(session.getId()); @@ -159,7 +163,8 @@ void given_validJsessionIdAndCsrfWithoutBearerToken_should_returnOk() throws Exc .cookie(new Cookie(CSRF_COOKIE_NAME, "test-csrf-token")) .header(CSRF_HEADER_NAME, "test-csrf-token") .contentType(MediaType.APPLICATION_JSON) - .content(SEARCH_BODY)) + .content(SEARCH_BODY) + .with(csrf())) .andExpect(status().isOk()); } }