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 28c8d98e79cd772d800fdecb39dbbdf780a74312 Author: Li Yang <[email protected]> AuthorDate: Sat Nov 7 14:31:39 2026 +0800 KYLIN-6123 enforce profiling project authorization --- .../org/apache/kylin/rest/service/JobService.java | 4 ++++ .../apache/kylin/rest/service/JobServiceTest.java | 28 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/data-loading-service/src/main/java/org/apache/kylin/rest/service/JobService.java b/src/data-loading-service/src/main/java/org/apache/kylin/rest/service/JobService.java index 294dc10b23..f5ec5f8e6c 100644 --- a/src/data-loading-service/src/main/java/org/apache/kylin/rest/service/JobService.java +++ b/src/data-loading-service/src/main/java/org/apache/kylin/rest/service/JobService.java @@ -175,6 +175,7 @@ public class JobService extends BasicService { } public void startProfileByProject(String project, String jobStepId, String params) { + aclEvaluate.checkProjectOperationPermission(project); if (!KylinConfig.getInstanceFromEnv().buildJobProfilingEnabled()) { throw new KylinException(JobErrorCode.PROFILING_NOT_ENABLED, String.format(Locale.ROOT, MsgPicker.getMsg().getProfilingNotEnabled(), BUILD_JOB_PROFILING_PARAMETER)); @@ -184,6 +185,7 @@ public class JobService extends BasicService { public void dumpProfileByProject(String project, String jobStepId, String params, Pair<InputStream, String> jobOutputAndDownloadFile) { + aclEvaluate.checkProjectOperationPermission(project); if (!KylinConfig.getInstanceFromEnv().buildJobProfilingEnabled()) { throw new KylinException(JobErrorCode.PROFILING_NOT_ENABLED, String.format(Locale.ROOT, MsgPicker.getMsg().getProfilingNotEnabled(), BUILD_JOB_PROFILING_PARAMETER)); @@ -200,6 +202,7 @@ public class JobService extends BasicService { MsgPicker.getMsg().getProfilingNotEnabled(), BUILD_JOB_PROFILING_PARAMETER)); } Pair<String, String> projectNameAndJobStepId = getProjectNameAndJobStepId(yarnAppId); + aclEvaluate.checkProjectOperationPermission(projectNameAndJobStepId.getFirst()); BuildAsyncProfileHelper.startProfile(projectNameAndJobStepId.getFirst(), projectNameAndJobStepId.getSecond(), params); } @@ -211,6 +214,7 @@ public class JobService extends BasicService { MsgPicker.getMsg().getProfilingNotEnabled(), BUILD_JOB_PROFILING_PARAMETER)); } Pair<String, String> projectNameAndJobStepId = getProjectNameAndJobStepId(yarnAppId); + aclEvaluate.checkProjectOperationPermission(projectNameAndJobStepId.getFirst()); InputStream jobOutput = BuildAsyncProfileHelper.dump(projectNameAndJobStepId.getFirst(), projectNameAndJobStepId.getSecond(), params); jobOutputAndDownloadFile.setFirst(jobOutput); diff --git a/src/data-loading-service/src/test/java/org/apache/kylin/rest/service/JobServiceTest.java b/src/data-loading-service/src/test/java/org/apache/kylin/rest/service/JobServiceTest.java index b3c83987e7..618021b2c3 100644 --- a/src/data-loading-service/src/test/java/org/apache/kylin/rest/service/JobServiceTest.java +++ b/src/data-loading-service/src/test/java/org/apache/kylin/rest/service/JobServiceTest.java @@ -800,6 +800,7 @@ public class JobServiceTest extends NLocalFileMetadataTestCase { errorMsg = e.getMessage(); } Assert.assertEquals(0, errorMsg.length()); + Mockito.verify(aclEvaluate).checkProjectOperationPermission(project); HadoopUtil.deletePath(HadoopUtil.getCurrentConfiguration(), actionPath); } @@ -837,6 +838,7 @@ public class JobServiceTest extends NLocalFileMetadataTestCase { errorMsg = e.getMessage(); } Assert.assertEquals(0, errorMsg.length()); + Mockito.verify(aclEvaluate).checkProjectOperationPermission(project); HadoopUtil.deletePath(HadoopUtil.getCurrentConfiguration(), actionPath); HadoopUtil.deletePath(HadoopUtil.getCurrentConfiguration(), dumpFilePath); t1.interrupt(); @@ -873,6 +875,7 @@ public class JobServiceTest extends NLocalFileMetadataTestCase { KylinConfig.getInstanceFromEnv().getJobTmpProfilerFlagsDir(project, jobStepId) + "/status"); HadoopUtil.writeStringToHdfs(ProfilerStatus.IDLE(), actionPath); jobService.startProfileByYarnAppId(yarnAppId, startParams); + Mockito.verify(aclEvaluate).checkProjectOperationPermission(project); HadoopUtil.deletePath(HadoopUtil.getCurrentConfiguration(), actionPath); } @@ -914,11 +917,36 @@ public class JobServiceTest extends NLocalFileMetadataTestCase { errorMsg = e.getMessage(); } Assert.assertEquals(0, errorMsg.length()); + Mockito.verify(aclEvaluate).checkProjectOperationPermission(project); HadoopUtil.deletePath(HadoopUtil.getCurrentConfiguration(), actionPath); HadoopUtil.deletePath(HadoopUtil.getCurrentConfiguration(), dumpFilePath); t1.interrupt(); } + @Test + public void testProfileOperationsByProjectCheckAcl() { + Mockito.doThrow(new AccessDeniedException("Access is denied")).when(aclEvaluate) + .checkProjectOperationPermission(project); + + Assert.assertThrows(AccessDeniedException.class, + () -> jobService.startProfileByProject(project, jobStepId, startParams)); + Assert.assertThrows(AccessDeniedException.class, + () -> jobService.dumpProfileByProject(project, jobStepId, dumpParams, new Pair<>())); + } + + @Test + public void testProfileOperationsByYarnAppIdCheckResolvedProjectAcl() { + overwriteSystemProp("kylin.engine.spark.cluster-manager-class-name", sparkClusterManagerName); + Mockito.doReturn(project).when(jobService).getProjectByJobId(jobId); + Mockito.doThrow(new AccessDeniedException("Access is denied")).when(aclEvaluate) + .checkProjectOperationPermission(project); + + Assert.assertThrows(AccessDeniedException.class, + () -> jobService.startProfileByYarnAppId(yarnAppId, startParams)); + Assert.assertThrows(AccessDeniedException.class, + () -> jobService.dumpProfileByYarnAppId(yarnAppId, dumpParams, new Pair<>())); + } + @Test public void testSetResponseLanguageNull() { HttpServletRequest mockRequest = mock(HttpServletRequest.class);
