This is an automated email from the ASF dual-hosted git repository. liyang-kylin pushed a commit to branch kylin5 in repository https://gitbox.apache.org/repos/asf/kylin.git
commit ee8612ec06fd26af55edf6e858d858b5cedaa604 Author: Li Yang <[email protected]> AuthorDate: Sat Nov 7 14:30:07 2026 +0800 KYLIN-6122 secure sparder event log cleanup --- .../apache/kylin/rest/controller/NSystemController.java | 3 ++- .../kylin/rest/controller/NSystemControllerTest.java | 13 +++++++++++++ .../org/apache/kylin/rest/service/ScheduleService.java | 2 ++ .../org/apache/kylin/rest/service/ScheduleServiceTest.java | 14 ++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/common-server/src/main/java/org/apache/kylin/rest/controller/NSystemController.java b/src/common-server/src/main/java/org/apache/kylin/rest/controller/NSystemController.java index bdd2878f26..7c933514ab 100644 --- a/src/common-server/src/main/java/org/apache/kylin/rest/controller/NSystemController.java +++ b/src/common-server/src/main/java/org/apache/kylin/rest/controller/NSystemController.java @@ -228,7 +228,8 @@ public class NSystemController extends NBasicController { */ @DeleteMapping(value = "clean_sparder_event_log") @ResponseBody - public EnvelopeResponse<String> queryNodeCleanSparderEventsLogs() { + public EnvelopeResponse<String> queryNodeCleanSparderEventsLogs(HttpServletRequest servletRequest) { + InternalRpcSecurity.requireGlobalAdminOrServiceToken(servletRequest); systemService.cleanSparderEventLog(); return new EnvelopeResponse<>(CODE_SUCCESS, "", ""); } diff --git a/src/common-server/src/test/java/org/apache/kylin/rest/controller/NSystemControllerTest.java b/src/common-server/src/test/java/org/apache/kylin/rest/controller/NSystemControllerTest.java index daa3da15f7..754dea9343 100644 --- a/src/common-server/src/test/java/org/apache/kylin/rest/controller/NSystemControllerTest.java +++ b/src/common-server/src/test/java/org/apache/kylin/rest/controller/NSystemControllerTest.java @@ -93,6 +93,9 @@ public class NSystemControllerTest extends NLocalFileMetadataTestCase { () -> nSystemController.doCleanupGarbage(new MockHttpServletRequest())); Assert.assertThrows(KylinException.class, () -> nSystemController.simulateInsertMeta(1, 1, new MockHttpServletRequest())); + Assert.assertThrows(KylinException.class, + () -> nSystemController.queryNodeCleanSparderEventsLogs(new MockHttpServletRequest())); + Mockito.verify(systemService, Mockito.never()).cleanSparderEventLog(); } @Test @@ -105,6 +108,16 @@ public class NSystemControllerTest extends NLocalFileMetadataTestCase { .andExpect(MockMvcResultMatchers.status().isOk()); } + @Test + public void testCleanSparderEventLogAcceptsServiceToken() throws Exception { + SecurityContextHolder.clearContext(); + mockMvc.perform(MockMvcRequestBuilders.delete("/api/system/clean_sparder_event_log") + .header(BroadcastEventReadyNotifier.BROADCAST_TOKEN_HEADER, getTestConfig().getBroadcastToken()) + .accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_JSON))) + .andExpect(MockMvcResultMatchers.status().isOk()); + Mockito.verify(systemService).cleanSparderEventLog(); + } + @Test public void testGetHostname() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/api/system/host").contentType(MediaType.APPLICATION_JSON) diff --git a/src/job-service/src/main/java/org/apache/kylin/rest/service/ScheduleService.java b/src/job-service/src/main/java/org/apache/kylin/rest/service/ScheduleService.java index 079639a6bc..5a34f8866b 100644 --- a/src/job-service/src/main/java/org/apache/kylin/rest/service/ScheduleService.java +++ b/src/job-service/src/main/java/org/apache/kylin/rest/service/ScheduleService.java @@ -300,6 +300,8 @@ public class ScheduleService extends BasicService { val httpHeaders = new HttpHeaders(); httpHeaders.add(HttpHeaders.CONTENT_TYPE, HTTP_VND_APACHE_KYLIN_V4_PUBLIC_JSON); + httpHeaders.add(BroadcastEventReadyNotifier.BROADCAST_TOKEN_HEADER, + KylinConfig.getInstanceFromEnv().getBroadcastToken()); val response = restTemplate.exchange(url, HttpMethod.DELETE, new HttpEntity<>(httpHeaders), String.class); receive(response, "noticeToQueryNode"); diff --git a/src/job-service/src/test/java/org/apache/kylin/rest/service/ScheduleServiceTest.java b/src/job-service/src/test/java/org/apache/kylin/rest/service/ScheduleServiceTest.java index 98b56d6f41..9e66177dcc 100644 --- a/src/job-service/src/test/java/org/apache/kylin/rest/service/ScheduleServiceTest.java +++ b/src/job-service/src/test/java/org/apache/kylin/rest/service/ScheduleServiceTest.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.util.concurrent.TimeoutException; import org.apache.kylin.common.KylinConfig; +import org.apache.kylin.common.persistence.transaction.BroadcastEventReadyNotifier; import org.apache.kylin.common.response.RestResponse; import org.apache.kylin.common.util.JsonUtil; import org.apache.kylin.common.util.NLocalFileMetadataTestCase; @@ -49,10 +50,12 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.ArgumentMatchers; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -183,4 +186,15 @@ public class ScheduleServiceTest extends NLocalFileMetadataTestCase { doThrow(TimeoutException.class).when(scheduleService).executeTask(any(), anyString(), anyLong()); scheduleService.doRoutineTaskForGlobal(); } + + @Test + public void testCleanSparderEventLogBroadcastIncludesServiceToken() { + ReflectionTestUtils.invokeMethod(scheduleService, "broadcastCleanSparderEventLogToAllNodes"); + + ArgumentCaptor<HttpEntity<HttpHeaders>> requestCaptor = ArgumentCaptor.forClass(HttpEntity.class); + Mockito.verify(restTemplate).exchange(anyString(), Mockito.eq(HttpMethod.DELETE), requestCaptor.capture(), + ArgumentMatchers.<Class<String>> any()); + Assert.assertEquals(getTestConfig().getBroadcastToken(), + requestCaptor.getValue().getHeaders().getFirst(BroadcastEventReadyNotifier.BROADCAST_TOKEN_HEADER)); + } }
