This is an automated email from the ASF dual-hosted git repository. nju_yaho pushed a commit to tag ebay-3.1.0-release-20200701 in repository https://gitbox.apache.org/repos/asf/kylin.git
commit 1709e64fe1cfdb64a3f32bd0f78c05f60dff308d Author: sanjulian <julian....@hotmail.com> AuthorDate: Wed May 27 14:55:30 2020 +0800 KYLIN-4529 Add user behavior audit log --- build/conf/kylin-server-log4j.properties | 11 +- .../java/org/apache/kylin/job/JobInstance.java | 4 + .../kylin/rest/util/UserBehaviorAuditLog.java | 94 ++++++++ .../kylin/rest/util/UserBehaviorAuditLogTest.java | 266 +++++++++++++++++++++ server/src/main/resources/kylinAuditLog.xml | 106 ++++++++ server/src/main/resources/kylinMetrics.xml | 2 +- server/src/main/webapp/WEB-INF/web.xml | 1 + 7 files changed, 482 insertions(+), 2 deletions(-) diff --git a/build/conf/kylin-server-log4j.properties b/build/conf/kylin-server-log4j.properties index bcaea65..7031b13 100644 --- a/build/conf/kylin-server-log4j.properties +++ b/build/conf/kylin-server-log4j.properties @@ -33,6 +33,12 @@ log4j.appender.realtime.Append=true log4j.appender.realtime.MaxFileSize=268435456 log4j.appender.realtime.MaxBackupIndex=10 +log4j.appender.audit=org.apache.log4j.DailyRollingFileAppender +log4j.appender.audit.layout=org.apache.log4j.PatternLayout +log4j.appender.audit.File=${catalina.home}/../logs/user-audit.log +log4j.appender.audit.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}:%L : %m%n +log4j.appender.audit.Append=true + #overall config log4j.rootLogger=INFO log4j.logger.org.apache.kylin=DEBUG,file @@ -45,4 +51,7 @@ log4j.logger.org.apache.kylin.job=DEBUG,realtime log4j.logger.org.apache.kylin.rest.service.StreamingCoordinatorService=DEBUG,realtime log4j.logger.org.apache.kylin.rest.service.StreamingV2Service=DEBUG,realtime log4j.logger.org.apache.kylin.rest.controller.StreamingCoordinatorController=DEBUG,realtime -log4j.logger.org.apache.kylin.rest.controller.StreamingV2Controller=DEBUG,realtime \ No newline at end of file +log4j.logger.org.apache.kylin.rest.controller.StreamingV2Controller=DEBUG,realtime + +#audit config +log4j.logger.org.apache.kylin.rest.util.UserBehaviorAuditLog=INFO, audit \ No newline at end of file diff --git a/core-job/src/main/java/org/apache/kylin/job/JobInstance.java b/core-job/src/main/java/org/apache/kylin/job/JobInstance.java index 1d78a25..a9b7759 100644 --- a/core-job/src/main/java/org/apache/kylin/job/JobInstance.java +++ b/core-job/src/main/java/org/apache/kylin/job/JobInstance.java @@ -533,4 +533,8 @@ public class JobInstance extends RootPersistentEntity implements Comparable<JobI return o.lastModified < this.lastModified ? -1 : o.lastModified > this.lastModified ? 1 : 0; } + @Override + public String toString() { + return "Job[name=" + getName() + "]"; + } } diff --git a/server-base/src/main/java/org/apache/kylin/rest/util/UserBehaviorAuditLog.java b/server-base/src/main/java/org/apache/kylin/rest/util/UserBehaviorAuditLog.java new file mode 100644 index 0000000..874b62f --- /dev/null +++ b/server-base/src/main/java/org/apache/kylin/rest/util/UserBehaviorAuditLog.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.kylin.rest.util; + +import java.util.Arrays; + +import org.apache.kylin.common.persistence.AclEntity; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.acls.model.Permission; +import org.springframework.security.acls.model.Sid; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +@Component("auditLog") +@Aspect +public class UserBehaviorAuditLog { + private static final Logger logger = LoggerFactory.getLogger(UserBehaviorAuditLog.class); + + /* base audit */ + public void auditAllParamWithSignature(JoinPoint joinPoint) { + logger.info("User: {} trigger {}, arguments: {}.", + SecurityContextHolder.getContext().getAuthentication().getName(), joinPoint.getSignature().getName(), + Arrays.toString(joinPoint.getArgs())); + } + + /* exception audit */ + public void executeFailed(JoinPoint joinPoint, Throwable reason) { + logger.info("User: {} execute {} failed, exception: {}", + SecurityContextHolder.getContext().getAuthentication().getName(), joinPoint.getSignature().getName(), + reason); + } + + public void finish(JoinPoint joinPoint) { + logger.info("User: {} execute {} finished.", SecurityContextHolder.getContext().getAuthentication().getName(), + joinPoint.getSignature().getName()); + } + + /* special job audit*/ + public void submitJobAudit(JoinPoint joinPoint) { + logger.info("User: {} submit job of {} for cube {} {}.", joinPoint.getArgs()[7], joinPoint.getArgs()[5], + joinPoint.getArgs()[0], joinPoint.getArgs()[1]); + } + + public void optimizeJobAudit(JoinPoint joinPoint) { + logger.info("User: {} submit job of optimization for cube {}.", joinPoint.getArgs()[2], joinPoint.getArgs()[0]); + } + + public void recoverSegmentOptimizeJobAudit(JoinPoint joinPoint) { + logger.info("User: {} submit job of recovering optimizing segment for {}.", joinPoint.getArgs()[1], + joinPoint.getArgs()[0]); + } + + /* access audit*/ + public void accessGrantAudit(AclEntity ae, Permission permission, Sid sid) { + logger.info("User: {} grant {} access[mask: {}, pattern: {}] to entity[{}].", + SecurityContextHolder.getContext().getAuthentication().getName(), sid, permission.getMask(), + permission.getPattern(), ae.getId()); + } + + public void accessUpdateAudit(AclEntity ae, int accessEntryId, Permission newPermission) { + logger.info("User: {} update entity[{}] accessEntryId[{}] to access[mask: {}, pattern: {}].", + SecurityContextHolder.getContext().getAuthentication().getName(), ae.getId(), accessEntryId, + newPermission.getMask(), newPermission.getPattern()); + } + + public void accessRevokeAudit(AclEntity ae, int accessEntryId) { + logger.info("User: {} revoke entity[{}] accessEntryId[{}] access.", + SecurityContextHolder.getContext().getAuthentication().getName(), ae.getId(), accessEntryId); + } + + public void accessCleanAudit(AclEntity ae, boolean deleteChildren) { + logger.info("User: {} clean entity[{}] access [delete children: {}].", + SecurityContextHolder.getContext().getAuthentication().getName(), ae.getId(), deleteChildren); + } +} diff --git a/server-base/src/test/java/org/apache/kylin/rest/util/UserBehaviorAuditLogTest.java b/server-base/src/test/java/org/apache/kylin/rest/util/UserBehaviorAuditLogTest.java new file mode 100644 index 0000000..67ca749 --- /dev/null +++ b/server-base/src/test/java/org/apache/kylin/rest/util/UserBehaviorAuditLogTest.java @@ -0,0 +1,266 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.kylin.rest.util; + +import static org.hamcrest.core.Is.is; + +import org.apache.kylin.common.persistence.AclEntity; +import org.apache.kylin.cube.CubeInstance; +import org.apache.kylin.cube.CubeSegment; +import org.apache.kylin.cube.model.CubeBuildTypeEnum; +import org.apache.kylin.metadata.model.SegmentRange; +import org.apache.log4j.Appender; +import org.apache.log4j.LogManager; +import org.apache.log4j.spi.LoggingEvent; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.security.acls.model.Permission; +import org.springframework.security.acls.model.Sid; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.context.SecurityContextImpl; + +@RunWith(MockitoJUnitRunner.class) +public class UserBehaviorAuditLogTest { + + @Mock + private Appender mockAppender; + + @Captor + private ArgumentCaptor captorLoggingEvent; + + @Before + public void setup() { + LogManager.getLogger(UserBehaviorAuditLog.class).addAppender(mockAppender); + + SecurityContextHolder holder = new SecurityContextHolder(); + + SecurityContext securityContext = new SecurityContextImpl(); + Authentication auth = new TestingAuthenticationToken("user_name", ""); + securityContext.setAuthentication(auth); + + holder.setContext(securityContext); + + } + + @After + public void teardown() { + LogManager.getLogger(UserBehaviorAuditLog.class).removeAppender(mockAppender); + } + + public JoinPoint mockBaseJoinPoint() { + JoinPoint mockJoinPoint = Mockito.mock(JoinPoint.class); + Signature mockSignature = Mockito.mock(Signature.class); + Mockito.when(mockJoinPoint.getSignature()).thenReturn(mockSignature); + Mockito.when(mockJoinPoint.getSignature().getName()).thenReturn("method_name"); + + return mockJoinPoint; + } + + @Test + public void testAuditLogauditAllParamWithSignature() { + UserBehaviorAuditLog auditLog = new UserBehaviorAuditLog(); + + JoinPoint mockJoinPoint = mockBaseJoinPoint(); + Object[] args = { "args1", "args2", "args3" }; + Mockito.when(mockJoinPoint.getArgs()).thenReturn(args); + + auditLog.auditAllParamWithSignature(mockJoinPoint); + + Mockito.verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture()); + LoggingEvent loggingEvent = (LoggingEvent) captorLoggingEvent.getValue(); + Assert.assertThat(loggingEvent.getRenderedMessage(), + is("User: user_name trigger method_name, arguments: [args1, args2, args3].")); + } + + @Test + public void testExecuteFailed() { + UserBehaviorAuditLog auditLog = new UserBehaviorAuditLog(); + + JoinPoint mockJoinPoint = mockBaseJoinPoint(); + Throwable reason = new Throwable("reason"); + + auditLog.executeFailed(mockJoinPoint, reason); + + Mockito.verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture()); + LoggingEvent loggingEvent = (LoggingEvent) captorLoggingEvent.getValue(); + Assert.assertThat(loggingEvent.getRenderedMessage(), + is("User: user_name execute method_name failed, exception: java.lang.Throwable: reason")); + } + + @Test + public void testFinish() { + UserBehaviorAuditLog auditLog = new UserBehaviorAuditLog(); + + JoinPoint mockJoinPoint = Mockito.mock(JoinPoint.class); + Signature mockSignature = Mockito.mock(Signature.class); + Mockito.when(mockJoinPoint.getSignature()).thenReturn(mockSignature); + Mockito.when(mockJoinPoint.getSignature().getName()).thenReturn("method_name"); + + auditLog.finish(mockJoinPoint); + + Mockito.verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture()); + LoggingEvent loggingEvent = (LoggingEvent) captorLoggingEvent.getValue(); + Assert.assertThat(loggingEvent.getRenderedMessage(), is("User: user_name execute method_name finished.")); + } + + @Test + public void testSubmitJobAudit() { + UserBehaviorAuditLog auditLog = new UserBehaviorAuditLog(); + + JoinPoint mockJoinPoint = mockBaseJoinPoint(); + CubeInstance cube = new CubeInstance(); + SegmentRange.TSRange tsRange = new SegmentRange.TSRange(0L, 99999L); + cube.setName("cube_name"); + Object[] args = { cube, tsRange, tsRange, null, null, CubeBuildTypeEnum.BUILD, true, "user_name", 0 }; + Mockito.when(mockJoinPoint.getArgs()).thenReturn(args); + + auditLog.submitJobAudit(mockJoinPoint); + + Mockito.verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture()); + LoggingEvent loggingEvent = (LoggingEvent) captorLoggingEvent.getValue(); + Assert.assertThat(loggingEvent.getRenderedMessage(), + is("User: user_name submit job of BUILD for cube CUBE[name=cube_name] TSRange[0,99999).")); + } + + @Test + public void testOptimizeJobAudit() { + UserBehaviorAuditLog auditLog = new UserBehaviorAuditLog(); + + JoinPoint mockJoinPoint = mockBaseJoinPoint(); + CubeInstance cube = new CubeInstance(); + cube.setName("cube_name"); + Object[] args = { cube, null, "user_name" }; + Mockito.when(mockJoinPoint.getArgs()).thenReturn(args); + + auditLog.optimizeJobAudit(mockJoinPoint); + + Mockito.verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture()); + LoggingEvent loggingEvent = (LoggingEvent) captorLoggingEvent.getValue(); + Assert.assertThat(loggingEvent.getRenderedMessage(), + is("User: user_name submit job of optimization for cube CUBE[name=cube_name].")); + } + + @Test + public void testRecoverSegmentOptimizeJobAudit() { + UserBehaviorAuditLog auditLog = new UserBehaviorAuditLog(); + + JoinPoint mockJoinPoint = mockBaseJoinPoint(); + CubeInstance cube = new CubeInstance(); + cube.setName("cube_name"); + CubeSegment segment = new CubeSegment(); + segment.setCubeInstance(cube); + segment.setName("segment_name"); + Object[] args = { segment, "user_name" }; + Mockito.when(mockJoinPoint.getArgs()).thenReturn(args); + + auditLog.recoverSegmentOptimizeJobAudit(mockJoinPoint); + + Mockito.verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture()); + LoggingEvent loggingEvent = (LoggingEvent) captorLoggingEvent.getValue(); + Assert.assertThat(loggingEvent.getRenderedMessage(), + is("User: user_name submit job of recovering optimizing segment for cube_name[segment_name].")); + } + + private AclEntity ae = new AclEntity() { + @Override + public String getId() { + return "uuid"; + } + }; + + private Permission permission = new Permission() { + @Override + public int getMask() { + return 16; + } + + @Override + public String getPattern() { + return "pattern"; + } + }; + + private Sid sid = new Sid() { + @Override + public String toString() { + return "PrincipalSid[user_name]"; + } + }; + + @Test + public void testAccessGrantAudit() { + UserBehaviorAuditLog auditLog = new UserBehaviorAuditLog(); + + auditLog.accessGrantAudit(ae, permission, sid); + + Mockito.verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture()); + LoggingEvent loggingEvent = (LoggingEvent) captorLoggingEvent.getValue(); + Assert.assertThat(loggingEvent.getRenderedMessage(), is( + "User: user_name grant PrincipalSid[user_name] access[mask: 16, pattern: pattern] to entity[uuid].")); + } + + @Test + public void testAccessUpdateAudit() { + UserBehaviorAuditLog auditLog = new UserBehaviorAuditLog(); + + auditLog.accessUpdateAudit(ae, 0, permission); + + Mockito.verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture()); + LoggingEvent loggingEvent = (LoggingEvent) captorLoggingEvent.getValue(); + Assert.assertThat(loggingEvent.getRenderedMessage(), + is("User: user_name update entity[uuid] accessEntryId[0] to access[mask: 16, pattern: pattern].")); + } + + @Test + public void testAccessRevokeAudit() { + UserBehaviorAuditLog auditLog = new UserBehaviorAuditLog(); + + auditLog.accessRevokeAudit(ae, 0); + + Mockito.verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture()); + LoggingEvent loggingEvent = (LoggingEvent) captorLoggingEvent.getValue(); + Assert.assertThat(loggingEvent.getRenderedMessage(), + is("User: user_name revoke entity[uuid] accessEntryId[0] access.")); + } + + @Test + public void testAccessCleanAudit() { + UserBehaviorAuditLog auditLog = new UserBehaviorAuditLog(); + + auditLog.accessCleanAudit(ae, true); + + Mockito.verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture()); + LoggingEvent loggingEvent = (LoggingEvent) captorLoggingEvent.getValue(); + Assert.assertThat(loggingEvent.getRenderedMessage(), + is("User: user_name clean entity[uuid] access [delete children: true].")); + } +} diff --git a/server/src/main/resources/kylinAuditLog.xml b/server/src/main/resources/kylinAuditLog.xml new file mode 100644 index 0000000..311963d --- /dev/null +++ b/server/src/main/resources/kylinAuditLog.xml @@ -0,0 +1,106 @@ +<!-- + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. See accompanying LICENSE file. +--> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-4.2.xsd + http://www.springframework.org/schema/aop + http://www.springframework.org/schema/aop/spring-aop-4.2.xsd"> + + <description>Kylin Audit Log</description> + + <aop:config> + <aop:aspect ref="auditLog"> + <!--cube audit--> + <aop:pointcut id="cubeBehavior" + expression="within(org.apache.kylin.rest.service.CubeService) + and @annotation(org.springframework.security.access.prepost.PreAuthorize) + and not execution(* org.apache.kylin.rest.service.CubeService.saveDraft(..)) + and not execution(* org.apache.kylin.rest.service.CubeService.getRecommendCuboidStatistics(..))"/> + <aop:before pointcut-ref="cubeBehavior" method="auditAllParamWithSignature"/> + <aop:after-throwing pointcut-ref="cubeBehavior" method="executeFailed" throwing="reason"/> + <aop:after pointcut-ref="cubeBehavior" method="finish"/> + + <!--job audit--> + <aop:pointcut id="existingJobBehavior" + expression="execution(* org.apache.kylin.rest.service.JobService.resumeJob(..)) + or execution(* org.apache.kylin.rest.service.JobService.cancelJob(..)) + or execution(* org.apache.kylin.rest.service.JobService.pauseJob(..)) + or execution(* org.apache.kylin.rest.service.JobService.dropJob(..)) + or execution(* org.apache.kylin.rest.service.JobService.rollbackJob(..))"/> + <aop:before pointcut-ref="existingJobBehavior" method="auditAllParamWithSignature"/> + <aop:pointcut id="submitJobBehavior" + expression="execution(* org.apache.kylin.rest.service.JobService.submitJob(..))"/> + <aop:before pointcut-ref="submitJobBehavior" method="submitJobAudit"/> + <aop:pointcut id="optimizeJobBehavior" + expression="execution(* org.apache.kylin.rest.service.JobService.submitOptimizeJob(..))"/> + <aop:before pointcut-ref="optimizeJobBehavior" method="optimizeJobAudit"/> + <aop:pointcut id="recoverSegmentOptimizeJobBehavior" + expression="execution(* org.apache.kylin.rest.service.JobService.submitRecoverSegmentOptimizeJob(..))"/> + <aop:before pointcut-ref="recoverSegmentOptimizeJobBehavior" method="recoverSegmentOptimizeJobAudit"/> + <aop:pointcut id="jobBehavior" + expression="within(org.apache.kylin.rest.service.JobService) and @annotation(org.springframework.security.access.prepost.PreAuthorize)"/> + <aop:after-throwing pointcut-ref="jobBehavior" method="executeFailed" throwing="reason"/> + <aop:after pointcut-ref="jobBehavior" method="finish"/> + + <!--model audit--> + <aop:pointcut id="modelBehavior" + expression="execution(* org.apache.kylin.rest.service.ModelService.createModelDesc(..)) + or execution(* org.apache.kylin.rest.service.ModelService.updateModelAndDesc(..)) + or execution(* org.apache.kylin.rest.service.ModelService.dropModel(..))"/> + <aop:before pointcut-ref="modelBehavior" method="auditAllParamWithSignature"/> + <aop:after-throwing pointcut-ref="modelBehavior" method="executeFailed" throwing="reason"/> + <aop:after pointcut-ref="modelBehavior" method="finish"/> + + <!--project audit--> + <aop:pointcut id="projectBehavior" + expression="within(org.apache.kylin.rest.service.ProjectService) + and @annotation(org.springframework.security.access.prepost.PreAuthorize) + and not execution(* org.apache.kylin.rest.service.ProjectService.addStreamingTable(..))"/> + <aop:before pointcut-ref="projectBehavior" method="auditAllParamWithSignature"/> + <aop:after-throwing pointcut-ref="projectBehavior" method="executeFailed" throwing="reason"/> + <aop:after pointcut-ref="projectBehavior" method="finish"/> + + <!--table audit--> + <aop:pointcut id="tableBehavior" + expression="execution(* org.apache.kylin.rest.service.TableService.loadHiveTablesToProject(..)) + or execution(* org.apache.kylin.rest.service.TableService.calculateCardinalityWithoutAuth(..)) + or execution(* org.apache.kylin.rest.service.TableService.unLoadHiveTable(..))"/> + <aop:before pointcut-ref="tableBehavior" method="auditAllParamWithSignature"/> + <aop:after-throwing pointcut-ref="tableBehavior" method="executeFailed" throwing="reason"/> + <aop:after pointcut-ref="tableBehavior" method="finish"/> + + <!--access audit--> + <aop:pointcut id="accessGrantBehavior" + expression="execution(* org.apache.kylin.rest.service.AccessService.grant(..)) and args(ae, permission, sid)"/> + <aop:before pointcut-ref="accessGrantBehavior" method="accessGrantAudit"/> + <aop:pointcut id="accessUpdateBehavior" + expression="execution(* org.apache.kylin.rest.service.AccessService.update(..)) and args(ae, accessEntryId, newPermission)"/> + <aop:before pointcut-ref="accessUpdateBehavior" method="accessUpdateAudit"/> + <aop:pointcut id="accessRevokeBehavior" + expression="execution(* org.apache.kylin.rest.service.AccessService.revoke(..)) and args(ae, accessEntryId)"/> + <aop:before pointcut-ref="accessRevokeBehavior" method="accessRevokeAudit"/> + <aop:pointcut id="accessCleanBehavior" + expression="execution(* org.apache.kylin.rest.service.AccessService.clean(..)) and args(ae, deleteChildren)"/> + <aop:before pointcut-ref="accessCleanBehavior" method="accessCleanAudit"/> + <aop:pointcut id="accessBehavior" + expression="within(org.apache.kylin.rest.service.AccessService) and @annotation(org.springframework.security.access.prepost.PreAuthorize)"/> + <aop:after-throwing pointcut-ref="accessBehavior" method="executeFailed" throwing="reason"/> + <aop:after pointcut-ref="accessBehavior" method="finish"/> + + </aop:aspect> + </aop:config> +</beans> \ No newline at end of file diff --git a/server/src/main/resources/kylinMetrics.xml b/server/src/main/resources/kylinMetrics.xml index 85c879f..2b89553 100644 --- a/server/src/main/resources/kylinMetrics.xml +++ b/server/src/main/resources/kylinMetrics.xml @@ -15,7 +15,7 @@ <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> + http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"> <description>Kylin Metrics Related Configuration (SystemCube)</description> diff --git a/server/src/main/webapp/WEB-INF/web.xml b/server/src/main/webapp/WEB-INF/web.xml index 8602c71..a88d1fb 100644 --- a/server/src/main/webapp/WEB-INF/web.xml +++ b/server/src/main/webapp/WEB-INF/web.xml @@ -45,6 +45,7 @@ classpath:applicationContext.xml classpath:kylinSecurity.xml classpath:kylinMetrics.xml + classpath:kylinAuditLog.xml classpath*:kylin-*-plugin.xml </param-value> </context-param>