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>

Reply via email to