SENTRY-812: Generate audit trail for Sentry generic model when authorization 
metadata change (Colin Ma, Reviewed by: Dapeng Sun)


Project: http://git-wip-us.apache.org/repos/asf/incubator-sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-sentry/commit/66b7096c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/66b7096c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/66b7096c

Branch: refs/heads/master
Commit: 66b7096cb14a6f52d16ea3e6efef1f1af65e35b2
Parents: cedfc57
Author: Colin Ma <[email protected]>
Authored: Tue Sep 29 15:30:34 2015 +0800
Committer: Colin Ma <[email protected]>
Committed: Tue Sep 29 15:30:34 2015 +0800

----------------------------------------------------------------------
 .../thrift/SentryGenericPolicyProcessor.java    |  60 +++-
 .../SentryGenericPolicyProcessorFactory.java    |   5 +-
 .../SentryGenericPolicyProcessorWrapper.java    |  39 +++
 .../db/log/entity/AuditMetadataLogEntity.java   | 137 ++-------
 .../db/log/entity/DBAuditMetadataLogEntity.java | 122 ++++++++
 .../db/log/entity/GMAuditMetadataLogEntity.java |  95 ++++++
 .../provider/db/log/entity/JsonLogEntity.java   |   2 +-
 .../db/log/entity/JsonLogEntityFactory.java     | 198 ++++++++++--
 .../provider/db/log/util/CommandUtil.java       |  89 ++++--
 .../sentry/provider/db/log/util/Constants.java  |  48 +++
 .../thrift/SentryPolicyStoreProcessor.java      |  68 ++++-
 .../TestAuditLogForSentryGenericService.java    | 299 +++++++++++++++++++
 .../log/entity/TestAuditMetadataLogEntity.java  |  69 -----
 .../entity/TestDbAuditMetadataLogEntity.java    |  69 +++++
 .../entity/TestGMAuditMetadataLogEntity.java    |  74 +++++
 .../db/log/entity/TestJsonLogEntityFactory.java |  75 +----
 .../log/entity/TestJsonLogEntityFactoryGM.java  | 259 ++++++++++++++++
 .../provider/db/log/util/TestCommandUtil.java   | 118 +++++---
 18 files changed, 1472 insertions(+), 354 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessor.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessor.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessor.java
index 94049d8..e7b6d17 100644
--- 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessor.java
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessor.java
@@ -36,8 +36,10 @@ import 
org.apache.sentry.provider.db.SentryInvalidInputException;
 import org.apache.sentry.provider.db.SentryNoSuchObjectException;
 import org.apache.sentry.provider.db.SentryThriftAPIMismatchException;
 import 
org.apache.sentry.provider.db.generic.service.persistent.PrivilegeObject;
-import 
org.apache.sentry.provider.db.generic.service.persistent.SentryStoreLayer;
 import 
org.apache.sentry.provider.db.generic.service.persistent.PrivilegeObject.Builder;
+import 
org.apache.sentry.provider.db.generic.service.persistent.SentryStoreLayer;
+import org.apache.sentry.provider.db.log.entity.JsonLogEntityFactory;
+import org.apache.sentry.provider.db.log.util.Constants;
 import org.apache.sentry.provider.db.service.persistent.CommitContext;
 import org.apache.sentry.provider.db.service.thrift.PolicyStoreConstants;
 import 
org.apache.sentry.provider.db.service.thrift.SentryConfigurationException;
@@ -60,6 +62,8 @@ import com.google.common.collect.Sets;
 
 public class SentryGenericPolicyProcessor implements 
SentryGenericPolicyService.Iface {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(SentryGenericPolicyProcessor.class);
+  private static final Logger AUDIT_LOGGER = LoggerFactory
+      .getLogger(Constants.AUDIT_LOGGER_NAME_GENERIC);
   private final Configuration conf;
   private final ImmutableSet<String> adminGroups;
   private final SentryStoreLayer store;
@@ -297,6 +301,15 @@ public class SentryGenericPolicyProcessor implements 
SentryGenericPolicyService.
     if (Status.OK.getCode() == respose.status.getValue()) {
       handerInvoker.create_sentry_role(respose.context, request, tResponse);
     }
+
+    try {
+      AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance()
+        .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog());
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for create role: " + 
e.getMessage();
+      LOGGER.error(msg, e);
+    }
     return tResponse;
   }
 
@@ -318,6 +331,15 @@ public class SentryGenericPolicyProcessor implements 
SentryGenericPolicyService.
     if (Status.OK.getCode() == respose.status.getValue()) {
       handerInvoker.drop_sentry_role(respose.context, request, tResponse);
     }
+
+    try {
+      AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance()
+        .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog());
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for drop role: " + e.getMessage();
+      LOGGER.error(msg, e);
+    }
     return tResponse;
   }
 
@@ -339,6 +361,15 @@ public class SentryGenericPolicyProcessor implements 
SentryGenericPolicyService.
     if (Status.OK.getCode() == respose.status.getValue()) {
       handerInvoker.alter_sentry_role_grant_privilege(respose.context, 
request, tResponse);
     }
+
+    try {
+      AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance()
+        .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog());
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for grant privilege to role: " + 
e.getMessage();
+      LOGGER.error(msg, e);
+    }
     return tResponse;
   }
 
@@ -360,6 +391,15 @@ public class SentryGenericPolicyProcessor implements 
SentryGenericPolicyService.
     if (Status.OK.getCode() == respose.status.getValue()) {
       handerInvoker.alter_sentry_role_revoke_privilege(respose.context, 
request, tResponse);
     }
+
+    try {
+      AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance()
+        .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog());
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for revoke privilege from role: " 
+ e.getMessage();
+      LOGGER.error(msg, e);
+    }
     return tResponse;
   }
 
@@ -383,6 +423,15 @@ public class SentryGenericPolicyProcessor implements 
SentryGenericPolicyService.
     if (Status.OK.getCode() == respose.status.getValue()) {
       handerInvoker.alter_sentry_role_add_groups(respose.context, request, 
tResponse);
     }
+
+    try {
+      AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance()
+        .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog());
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for add role to group: " + 
e.getMessage();
+      LOGGER.error(msg, e);
+    }
     return tResponse;
   }
 
@@ -406,6 +455,15 @@ public class SentryGenericPolicyProcessor implements 
SentryGenericPolicyService.
     if (Status.OK.getCode() == respose.status.getValue()) {
       handerInvoker.alter_sentry_role_delete_groups(respose.context, request, 
tResponse);
     }
+
+    try {
+      AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance()
+        .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog());
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for delete role from group: " + 
e.getMessage();
+      LOGGER.error(msg, e);
+    }
     return tResponse;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessorFactory.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessorFactory.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessorFactory.java
index 71ce579..1cce1fc 100644
--- 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessorFactory.java
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessorFactory.java
@@ -18,8 +18,6 @@
 package org.apache.sentry.provider.db.generic.service.thrift;
 
 import org.apache.hadoop.conf.Configuration;
-import 
org.apache.sentry.provider.db.generic.service.thrift.SentryGenericPolicyService;
-import 
org.apache.sentry.provider.db.service.thrift.PolicyStoreConstants.PolicyStoreServerConfig;
 import org.apache.sentry.service.thrift.ProcessorFactory;
 import org.apache.thrift.TMultiplexedProcessor;
 import org.apache.thrift.TProcessor;
@@ -33,7 +31,8 @@ public class SentryGenericPolicyProcessorFactory extends 
ProcessorFactory {
   @Override
   public boolean register(TMultiplexedProcessor multiplexedProcessor) throws 
Exception {
     SentryGenericPolicyProcessor processHandler = new 
SentryGenericPolicyProcessor(conf);
-    TProcessor processor = new 
SentryGenericPolicyService.Processor<SentryGenericPolicyService.Iface>(processHandler);
+    TProcessor processor = new 
SentryGenericPolicyProcessorWrapper<SentryGenericPolicyService.Iface>(
+        processHandler);
     
multiplexedProcessor.registerProcessor(SentryGenericPolicyProcessor.SENTRY_GENERIC_SERVICE_NAME,
 processor);
     return true;
   }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessorWrapper.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessorWrapper.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessorWrapper.java
new file mode 100644
index 0000000..d320d0f
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessorWrapper.java
@@ -0,0 +1,39 @@
+/**
+ * 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.sentry.provider.db.generic.service.thrift;
+
+import org.apache.sentry.provider.db.service.thrift.ThriftUtil;
+import org.apache.thrift.TException;
+import org.apache.thrift.protocol.TProtocol;
+
+public class SentryGenericPolicyProcessorWrapper<I extends 
SentryGenericPolicyService.Iface>
+    extends 
SentryGenericPolicyService.Processor<SentryGenericPolicyService.Iface> {
+
+  public SentryGenericPolicyProcessorWrapper(I iface) {
+    super(iface);
+  }
+
+  @Override
+  public boolean process(TProtocol in, TProtocol out) throws TException {
+    // set the ip and impersonator for audit log
+    ThriftUtil.setIpAddress(in);
+    ThriftUtil.setImpersonator(in);
+    return super.process(in, out);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/AuditMetadataLogEntity.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/AuditMetadataLogEntity.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/AuditMetadataLogEntity.java
index 6b63045..f3eb95b 100644
--- 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/AuditMetadataLogEntity.java
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/AuditMetadataLogEntity.java
@@ -19,45 +19,30 @@
 package org.apache.sentry.provider.db.log.entity;
 
 import java.io.IOException;
-import java.io.StringWriter;
 
-import org.apache.sentry.provider.db.log.util.Constants;
 import org.codehaus.jackson.JsonFactory;
-import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonNode;
 import org.codehaus.jackson.map.MappingJsonFactory;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.node.ContainerNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class AuditMetadataLogEntity implements JsonLogEntity {
-
-  private static final Logger LOGGER = LoggerFactory
-      .getLogger(AuditMetadataLogEntity.class);
-  private static final JsonFactory factory = new MappingJsonFactory();
-  private String serviceName;
-  private String userName;
-  private String impersonator;
-  private String ipAddress;
-  private String operation;
-  private String eventTime;
-  private String operationText;
-  private String allowed;
-  private String databaseName;
-  private String tableName;
-  private String columnName;
-  private String resourcePath;
-  private String objectType;
-
-  public AuditMetadataLogEntity() {
-  }
-
-  public AuditMetadataLogEntity(String serviceName, String userName,
-      String impersonator, String ipAddress, String operation,
-      String eventTime, String operationText, String allowed,
-      String databaseName, String tableName, String columnName,
-      String resourcePath, String objectType) {
+
+abstract public class AuditMetadataLogEntity implements JsonLogEntity {
+
+  static final JsonFactory factory = new MappingJsonFactory();
+  String serviceName;
+  String userName;
+  String impersonator;
+  String ipAddress;
+  String operation;
+  String eventTime;
+  String operationText;
+  String allowed;
+  String objectType;
+  String component;
+
+  void setCommonAttr(String serviceName, String userName, String impersonator, 
String ipAddress,
+      String operation, String eventTime, String operationText, String 
allowed, String objectType,
+      String component) {
     this.serviceName = serviceName;
     this.userName = userName;
     this.impersonator = impersonator;
@@ -66,52 +51,8 @@ public class AuditMetadataLogEntity implements JsonLogEntity 
{
     this.eventTime = eventTime;
     this.operationText = operationText;
     this.allowed = allowed;
-    this.databaseName = databaseName;
-    this.tableName = tableName;
-    this.columnName = columnName;
-    this.resourcePath = resourcePath;
     this.objectType = objectType;
-  }
-
-  @Override
-  public String toJsonFormatLog() {
-    StringWriter stringWriter = new StringWriter();
-    JsonGenerator json = null;
-    try {
-      json = factory.createJsonGenerator(stringWriter);
-      json.writeStartObject();
-      json.writeStringField(Constants.LOG_FIELD_SERVICE_NAME, serviceName);
-      json.writeStringField(Constants.LOG_FIELD_USER_NAME, userName);
-      json.writeStringField(Constants.LOG_FIELD_IMPERSONATOR, impersonator);
-      json.writeStringField(Constants.LOG_FIELD_IP_ADDRESS, ipAddress);
-      json.writeStringField(Constants.LOG_FIELD_OPERATION, operation);
-      json.writeStringField(Constants.LOG_FIELD_EVENT_TIME, eventTime);
-      json.writeStringField(Constants.LOG_FIELD_OPERATION_TEXT, operationText);
-      json.writeStringField(Constants.LOG_FIELD_ALLOWED, allowed);
-      json.writeStringField(Constants.LOG_FIELD_DATABASE_NAME, databaseName);
-      json.writeStringField(Constants.LOG_FIELD_TABLE_NAME, tableName);
-      json.writeStringField(Constants.LOG_FIELD_COLUMN_NAME, columnName);
-      json.writeStringField(Constants.LOG_FIELD_RESOURCE_PATH, resourcePath);
-      json.writeStringField(Constants.LOG_FIELD_OBJECT_TYPE, objectType);
-      json.writeEndObject();
-      json.flush();
-    } catch (IOException e) {
-      // if there has error when creating the audit log in json, set the audit
-      // log to empty.
-      stringWriter = new StringWriter();
-      String msg = "Error creating audit log in json format: " + 
e.getMessage();
-      LOGGER.error(msg, e);
-    } finally {
-      try {
-        if (json != null) {
-          json.close();
-        }
-      } catch (IOException e) {
-        LOGGER.error("Error closing JsonGenerator", e);
-      }
-    }
-
-    return stringWriter.toString();
+    this.component = component;
   }
 
   public String getServiceName() {
@@ -178,38 +119,6 @@ public class AuditMetadataLogEntity implements 
JsonLogEntity {
     this.allowed = allowed;
   }
 
-  public String getDatabaseName() {
-    return databaseName;
-  }
-
-  public void setDatabaseName(String databaseName) {
-    this.databaseName = databaseName;
-  }
-
-  public String getTableName() {
-    return tableName;
-  }
-
-  public void setTableName(String tableName) {
-    this.tableName = tableName;
-  }
-
-  public String getColumnName() {
-    return columnName;
-  }
-
-  public void setColumnName(String columnName) {
-    this.columnName = columnName;
-  }
-
-  public String getResourcePath() {
-    return resourcePath;
-  }
-
-  public void setResourcePath(String resourcePath) {
-    this.resourcePath = resourcePath;
-  }
-
   public String getObjectType() {
     return objectType;
   }
@@ -218,6 +127,14 @@ public class AuditMetadataLogEntity implements 
JsonLogEntity {
     this.objectType = objectType;
   }
 
+  public String getComponent() {
+    return component;
+  }
+
+  public void setComponent(String component) {
+    this.component = component;
+  }
+
   /**
    * For use in tests
    * 

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/DBAuditMetadataLogEntity.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/DBAuditMetadataLogEntity.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/DBAuditMetadataLogEntity.java
new file mode 100644
index 0000000..95afe52
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/DBAuditMetadataLogEntity.java
@@ -0,0 +1,122 @@
+/**
+ * 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.sentry.provider.db.log.entity;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+import org.apache.sentry.provider.db.log.util.Constants;
+import org.codehaus.jackson.JsonGenerator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DBAuditMetadataLogEntity extends AuditMetadataLogEntity {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(DBAuditMetadataLogEntity.class);
+
+  private String databaseName;
+  private String tableName;
+  private String columnName;
+  private String resourcePath;
+
+  public DBAuditMetadataLogEntity() {
+  }
+
+  public DBAuditMetadataLogEntity(String serviceName, String userName, String 
impersonator,
+      String ipAddress, String operation, String eventTime, String 
operationText, String allowed,
+      String objectType, String component, String databaseName, String 
tableName,
+      String columnName, String resourcePath) {
+    setCommonAttr(serviceName, userName, impersonator, ipAddress, operation, 
eventTime,
+        operationText, allowed, objectType, component);
+    this.databaseName = databaseName;
+    this.tableName = tableName;
+    this.columnName = columnName;
+    this.resourcePath = resourcePath;
+  }
+
+  public String getDatabaseName() {
+    return databaseName;
+  }
+
+  public void setDatabaseName(String databaseName) {
+    this.databaseName = databaseName;
+  }
+
+  public String getTableName() {
+    return tableName;
+  }
+
+  public void setTableName(String tableName) {
+    this.tableName = tableName;
+  }
+
+  public String getColumnName() {
+    return columnName;
+  }
+
+  public void setColumnName(String columnName) {
+    this.columnName = columnName;
+  }
+
+  public String getResourcePath() {
+    return resourcePath;
+  }
+
+  public void setResourcePath(String resourcePath) {
+    this.resourcePath = resourcePath;
+  }
+
+  @Override
+  public String toJsonFormatLog() throws Exception {
+    StringWriter stringWriter = new StringWriter();
+    JsonGenerator json = null;
+    try {
+      json = factory.createJsonGenerator(stringWriter);
+      json.writeStartObject();
+      json.writeStringField(Constants.LOG_FIELD_SERVICE_NAME, serviceName);
+      json.writeStringField(Constants.LOG_FIELD_USER_NAME, userName);
+      json.writeStringField(Constants.LOG_FIELD_IMPERSONATOR, impersonator);
+      json.writeStringField(Constants.LOG_FIELD_IP_ADDRESS, ipAddress);
+      json.writeStringField(Constants.LOG_FIELD_OPERATION, operation);
+      json.writeStringField(Constants.LOG_FIELD_EVENT_TIME, eventTime);
+      json.writeStringField(Constants.LOG_FIELD_OPERATION_TEXT, operationText);
+      json.writeStringField(Constants.LOG_FIELD_ALLOWED, allowed);
+      json.writeStringField(Constants.LOG_FIELD_DATABASE_NAME, databaseName);
+      json.writeStringField(Constants.LOG_FIELD_TABLE_NAME, tableName);
+      json.writeStringField(Constants.LOG_FIELD_COLUMN_NAME, columnName);
+      json.writeStringField(Constants.LOG_FIELD_RESOURCE_PATH, resourcePath);
+      json.writeStringField(Constants.LOG_FIELD_OBJECT_TYPE, objectType);
+      json.writeEndObject();
+      json.flush();
+    } catch (IOException e) {
+      String msg = "Error creating audit log in json format: " + 
e.getMessage();
+      LOGGER.error(msg, e);
+      throw e;
+    } finally {
+      try {
+        if (json != null) {
+          json.close();
+        }
+      } catch (IOException e) {
+        throw e;
+      }
+    }
+
+    return stringWriter.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/GMAuditMetadataLogEntity.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/GMAuditMetadataLogEntity.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/GMAuditMetadataLogEntity.java
new file mode 100644
index 0000000..25d55e0
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/GMAuditMetadataLogEntity.java
@@ -0,0 +1,95 @@
+/**
+ * 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.sentry.provider.db.log.entity;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.sentry.provider.db.log.util.Constants;
+import org.codehaus.jackson.JsonGenerator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GMAuditMetadataLogEntity extends AuditMetadataLogEntity {
+
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(GMAuditMetadataLogEntity.class);
+  private Map<String, String> privilegesMap;
+
+  public GMAuditMetadataLogEntity() {
+    privilegesMap = new LinkedHashMap<String, String>();
+  }
+
+  public GMAuditMetadataLogEntity(String serviceName, String userName, String 
impersonator,
+      String ipAddress, String operation, String eventTime, String 
operationText, String allowed,
+      String objectType, String component, Map<String, String> privilegesMap) {
+    setCommonAttr(serviceName, userName, impersonator, ipAddress, operation, 
eventTime,
+        operationText, allowed, objectType, component);
+    this.privilegesMap = privilegesMap;
+  }
+
+  @Override
+  public String toJsonFormatLog() throws Exception {
+    StringWriter stringWriter = new StringWriter();
+    JsonGenerator json = null;
+    try {
+      json = factory.createJsonGenerator(stringWriter);
+      json.writeStartObject();
+      json.writeStringField(Constants.LOG_FIELD_SERVICE_NAME, serviceName);
+      json.writeStringField(Constants.LOG_FIELD_USER_NAME, userName);
+      json.writeStringField(Constants.LOG_FIELD_IMPERSONATOR, impersonator);
+      json.writeStringField(Constants.LOG_FIELD_IP_ADDRESS, ipAddress);
+      json.writeStringField(Constants.LOG_FIELD_OPERATION, operation);
+      json.writeStringField(Constants.LOG_FIELD_EVENT_TIME, eventTime);
+      json.writeStringField(Constants.LOG_FIELD_OPERATION_TEXT, operationText);
+      json.writeStringField(Constants.LOG_FIELD_ALLOWED, allowed);
+      for (Map.Entry<String, String> entry : privilegesMap.entrySet()) {
+        json.writeStringField(entry.getKey(), entry.getValue());
+      }
+      json.writeStringField(Constants.LOG_FIELD_OBJECT_TYPE, objectType);
+      json.writeStringField(Constants.LOG_FIELD_COMPONENT, component);
+      json.writeEndObject();
+      json.flush();
+    } catch (IOException e) {
+      String msg = "Error creating audit log in json format: " + 
e.getMessage();
+      LOGGER.error(msg, e);
+      throw e;
+    } finally {
+      try {
+        if (json != null) {
+          json.close();
+        }
+      } catch (IOException e) {
+        throw e;
+      }
+    }
+
+    return stringWriter.toString();
+  }
+
+  public Map<String, String> getPrivilegesMap() {
+    return privilegesMap;
+  }
+
+  public void setPrivilegesMap(Map<String, String> privilegesMap) {
+    this.privilegesMap = privilegesMap;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntity.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntity.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntity.java
index 7ad6966..f7edeb1 100644
--- 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntity.java
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntity.java
@@ -20,6 +20,6 @@ package org.apache.sentry.provider.db.log.entity;
 
 public interface JsonLogEntity {
 
-  public String toJsonFormatLog();
+  public String toJsonFormatLog() throws Exception;
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntityFactory.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntityFactory.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntityFactory.java
index 3ad46c4..c29b88e 100644
--- 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntityFactory.java
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntityFactory.java
@@ -18,9 +18,14 @@
 
 package org.apache.sentry.provider.db.log.entity;
 
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable;
 import org.apache.sentry.provider.db.log.util.CommandUtil;
 import org.apache.sentry.provider.db.log.util.Constants;
 import 
org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleAddGroupsRequest;
@@ -35,12 +40,14 @@ import 
org.apache.sentry.provider.db.service.thrift.TCreateSentryRoleRequest;
 import org.apache.sentry.provider.db.service.thrift.TCreateSentryRoleResponse;
 import org.apache.sentry.provider.db.service.thrift.TDropSentryRoleRequest;
 import org.apache.sentry.provider.db.service.thrift.TDropSentryRoleResponse;
+import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
 import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
 import org.apache.sentry.provider.db.service.thrift.ThriftUtil;
 import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
 import org.apache.sentry.service.thrift.Status;
 import org.apache.sentry.service.thrift.TSentryResponseStatus;
 
+import com.google.common.base.Joiner;
 import com.google.common.collect.ImmutableSet;
 
 public class JsonLogEntityFactory {
@@ -54,26 +61,29 @@ public class JsonLogEntityFactory {
     return factory;
   }
 
+  // log entity for hive/impala create role
   public JsonLogEntity createJsonLogEntity(TCreateSentryRoleRequest request,
       TCreateSentryRoleResponse response, Configuration conf) {
-    AuditMetadataLogEntity amle = createCommonAMLE(conf, response.getStatus(),
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, 
response.getStatus(),
         request.getRequestorUserName(), request.getClass().getName());
-    amle.setOperationText(CommandUtil.createCmdForCreateOrDropRole(
+    hamle.setOperationText(CommandUtil.createCmdForCreateOrDropRole(
         request.getRoleName(), true));
 
-    return amle;
+    return hamle;
   }
 
+  // log entity for hive/impala drop role
   public JsonLogEntity createJsonLogEntity(TDropSentryRoleRequest request,
       TDropSentryRoleResponse response, Configuration conf) {
-    AuditMetadataLogEntity amle = createCommonAMLE(conf, response.getStatus(),
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, 
response.getStatus(),
         request.getRequestorUserName(), request.getClass().getName());
-    amle.setOperationText(CommandUtil.createCmdForCreateOrDropRole(
+    hamle.setOperationText(CommandUtil.createCmdForCreateOrDropRole(
         request.getRoleName(), false));
 
-    return amle;
+    return hamle;
   }
 
+  // log entity for hive/impala grant privilege
   public Set<JsonLogEntity> createJsonLogEntitys(
       TAlterSentryRoleGrantPrivilegeRequest request,
       TAlterSentryRoleGrantPrivilegeResponse response, Configuration conf) {
@@ -90,15 +100,16 @@ public class JsonLogEntityFactory {
   private JsonLogEntity createJsonLogEntity(
       TAlterSentryRoleGrantPrivilegeRequest request, TSentryPrivilege 
privilege,
       TAlterSentryRoleGrantPrivilegeResponse response, Configuration conf) {
-    AuditMetadataLogEntity amle = createCommonAMLE(conf, response.getStatus(),
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, 
response.getStatus(),
         request.getRequestorUserName(), request.getClass().getName());
-    amle.setOperationText(CommandUtil.createCmdForGrantPrivilege(request));
-    amle.setDatabaseName(privilege.getDbName());
-    amle.setTableName(privilege.getTableName());
-    amle.setResourcePath(privilege.getURI());
-    return amle;
+    hamle.setOperationText(CommandUtil.createCmdForGrantPrivilege(request));
+    hamle.setDatabaseName(privilege.getDbName());
+    hamle.setTableName(privilege.getTableName());
+    hamle.setResourcePath(privilege.getURI());
+    return hamle;
   }
 
+  // log entity for hive/impala revoke privilege
   public Set<JsonLogEntity> createJsonLogEntitys(
       TAlterSentryRoleRevokePrivilegeRequest request,
       TAlterSentryRoleRevokePrivilegeResponse response, Configuration conf) {
@@ -115,34 +126,54 @@ public class JsonLogEntityFactory {
   private JsonLogEntity createJsonLogEntity(
       TAlterSentryRoleRevokePrivilegeRequest request, TSentryPrivilege 
privilege,
       TAlterSentryRoleRevokePrivilegeResponse response, Configuration conf) {
-    AuditMetadataLogEntity amle = createCommonAMLE(conf, response.getStatus(),
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, 
response.getStatus(),
         request.getRequestorUserName(), request.getClass().getName());
-    amle.setOperationText(CommandUtil.createCmdForRevokePrivilege(request));
-    amle.setDatabaseName(privilege.getDbName());
-    amle.setTableName(privilege.getTableName());
-    amle.setResourcePath(privilege.getURI());
+    hamle.setOperationText(CommandUtil.createCmdForRevokePrivilege(request));
+    hamle.setDatabaseName(privilege.getDbName());
+    hamle.setTableName(privilege.getTableName());
+    hamle.setResourcePath(privilege.getURI());
 
-    return amle;
+    return hamle;
   }
 
+  // log entity for hive/impala add role to group
   public JsonLogEntity createJsonLogEntity(
       TAlterSentryRoleAddGroupsRequest request,
       TAlterSentryRoleAddGroupsResponse response, Configuration conf) {
-    AuditMetadataLogEntity amle = createCommonAMLE(conf, response.getStatus(),
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, 
response.getStatus(),
         request.getRequestorUserName(), request.getClass().getName());
-    amle.setOperationText(CommandUtil.createCmdForRoleAddGroup(request));
+    String groups = getGroupsStr(request.getGroupsIterator());
+    
hamle.setOperationText(CommandUtil.createCmdForRoleAddGroup(request.getRoleName(),
 groups));
 
-    return amle;
+    return hamle;
   }
 
+  // log entity for hive/impala delete role from group
   public JsonLogEntity createJsonLogEntity(
       TAlterSentryRoleDeleteGroupsRequest request,
       TAlterSentryRoleDeleteGroupsResponse response, Configuration conf) {
-    AuditMetadataLogEntity amle = createCommonAMLE(conf, response.getStatus(),
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, 
response.getStatus(),
         request.getRequestorUserName(), request.getClass().getName());
-    amle.setOperationText(CommandUtil.createCmdForRoleDeleteGroup(request));
+    String groups = getGroupsStr(request.getGroupsIterator());
+    
hamle.setOperationText(CommandUtil.createCmdForRoleDeleteGroup(request.getRoleName(),
 groups));
 
-    return amle;
+    return hamle;
+  }
+
+  private String getGroupsStr(Iterator<TSentryGroup> iter) {
+    StringBuilder groups = new StringBuilder("");
+    if (iter != null) {
+      boolean commaFlg = false;
+      while (iter.hasNext()) {
+        if (commaFlg) {
+          groups.append(", ");
+        } else {
+          commaFlg = true;
+        }
+        groups.append(iter.next().getGroupName());
+      }
+    }
+    return groups.toString();
   }
 
   public String isAllowed(TSentryResponseStatus status) {
@@ -152,10 +183,120 @@ public class JsonLogEntityFactory {
     return Constants.FALSE;
   }
 
-  private AuditMetadataLogEntity createCommonAMLE(Configuration conf,
-      TSentryResponseStatus responseStatus, String userName,
-      String requestClassName) {
-    AuditMetadataLogEntity amle = new AuditMetadataLogEntity();
+  // log entity for generic model create role
+  public JsonLogEntity createJsonLogEntity(
+      
org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleRequest 
request,
+      
org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleResponse 
response,
+      Configuration conf) {
+    GMAuditMetadataLogEntity gmamle = createCommonGMAMLE(conf, 
response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName(), 
request.getComponent());
+    
gmamle.setOperationText(CommandUtil.createCmdForCreateOrDropRole(request.getRoleName(),
 true));
+
+    return gmamle;
+  }
+
+  // log entity for generic model drop role
+  public JsonLogEntity createJsonLogEntity(
+      
org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleRequest 
request,
+      
org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleResponse 
response,
+      Configuration conf) {
+    GMAuditMetadataLogEntity gmamle = createCommonGMAMLE(conf, 
response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName(), 
request.getComponent());
+    
gmamle.setOperationText(CommandUtil.createCmdForCreateOrDropRole(request.getRoleName(),
 false));
+
+    return gmamle;
+  }
+
+  // log entity for generic model grant privilege
+  public JsonLogEntity createJsonLogEntity(
+      
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest
 request,
+      
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeResponse
 response,
+      Configuration conf) {
+    GMAuditMetadataLogEntity gmamle = createCommonGMAMLE(conf, 
response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName(), 
request.getComponent());
+    if (request.getPrivilege() != null) {
+      List<TAuthorizable> authorizables = 
request.getPrivilege().getAuthorizables();
+      Map<String, String> privilegesMap = new LinkedHashMap<String, String>();
+      if (authorizables != null) {
+        for (TAuthorizable authorizable : authorizables) {
+          privilegesMap.put(authorizable.getType(), authorizable.getName());
+        }
+      }
+      gmamle.setPrivilegesMap(privilegesMap);
+    }
+    gmamle.setOperationText(CommandUtil.createCmdForGrantGMPrivilege(request));
+
+    return gmamle;
+  }
+
+  // log entity for generic model revoke privilege
+  public JsonLogEntity createJsonLogEntity(
+      
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest
 request,
+      
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeResponse
 response,
+      Configuration conf) {
+    GMAuditMetadataLogEntity gmamle = createCommonGMAMLE(conf, 
response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName(), 
request.getComponent());
+    if (request.getPrivilege() != null) {
+      List<TAuthorizable> authorizables = 
request.getPrivilege().getAuthorizables();
+      Map<String, String> privilegesMap = new LinkedHashMap<String, String>();
+      if (authorizables != null) {
+        for (TAuthorizable authorizable : authorizables) {
+          privilegesMap.put(authorizable.getType(), authorizable.getName());
+        }
+      }
+      gmamle.setPrivilegesMap(privilegesMap);
+    }
+    
gmamle.setOperationText(CommandUtil.createCmdForRevokeGMPrivilege(request));
+
+    return gmamle;
+  }
+
+  // log entity for generic model add role to group
+  public JsonLogEntity createJsonLogEntity(
+      
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsRequest
 request,
+      
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsResponse
 response,
+      Configuration conf) {
+    GMAuditMetadataLogEntity gmamle = createCommonGMAMLE(conf, 
response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName(), 
request.getComponent());
+    Joiner joiner = Joiner.on(",");
+    String groups = joiner.join(request.getGroupsIterator());
+    
gmamle.setOperationText(CommandUtil.createCmdForRoleAddGroup(request.getRoleName(),
 groups));
+
+    return gmamle;
+  }
+
+  // log entity for hive delete role from group
+  public JsonLogEntity createJsonLogEntity(
+      
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsRequest
 request,
+      
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsResponse
 response,
+      Configuration conf) {
+    GMAuditMetadataLogEntity gmamle = createCommonGMAMLE(conf, 
response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName(), 
request.getComponent());
+    Joiner joiner = Joiner.on(",");
+    String groups = joiner.join(request.getGroupsIterator());
+    
gmamle.setOperationText(CommandUtil.createCmdForRoleDeleteGroup(request.getRoleName(),
 groups));
+
+    return gmamle;
+  }
+
+  private DBAuditMetadataLogEntity createCommonHAMLE(Configuration conf,
+      TSentryResponseStatus responseStatus, String userName, String 
requestClassName) {
+    DBAuditMetadataLogEntity hamle = new DBAuditMetadataLogEntity();
+    setCommAttrForAMLE(hamle, conf, responseStatus, userName, 
requestClassName);
+    return hamle;
+  }
+
+  private GMAuditMetadataLogEntity createCommonGMAMLE(Configuration conf,
+      TSentryResponseStatus responseStatus, String userName, String 
requestClassName,
+      String component) {
+    GMAuditMetadataLogEntity gmamle = new GMAuditMetadataLogEntity();
+    setCommAttrForAMLE(gmamle, conf, responseStatus, userName, 
requestClassName);
+    gmamle.setComponent(component);
+    return gmamle;
+  }
+
+  private void setCommAttrForAMLE(AuditMetadataLogEntity amle, Configuration 
conf,
+      TSentryResponseStatus responseStatus, String userName, String 
requestClassName) {
     amle.setUserName(userName);
     amle.setServiceName(conf.get(ServerConfig.SENTRY_SERVICE_NAME,
         ServerConfig.SENTRY_SERVICE_NAME_DEFAULT).trim());
@@ -166,6 +307,5 @@ public class JsonLogEntityFactory {
     amle.setAllowed(isAllowed(responseStatus));
     amle.setObjectType(Constants.requestTypeToObjectTypeMap
         .get(requestClassName));
-    return amle;
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java
index 741cfdc..d6aecd1 100644
--- 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java
@@ -21,18 +21,17 @@ package org.apache.sentry.provider.db.log.util;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.util.Enumeration;
-import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 
 import org.apache.sentry.core.model.db.AccessConstants;
-import 
org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleAddGroupsRequest;
-import 
org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleDeleteGroupsRequest;
+import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable;
 import 
org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleGrantPrivilegeRequest;
 import 
org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleRevokePrivilegeRequest;
 import org.apache.sentry.provider.db.service.thrift.TSentryGrantOption;
-import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
 import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
 import org.apache.sentry.service.thrift.ServiceConstants.PrivilegeScope;
+import org.datanucleus.util.StringUtils;
 
 import com.google.common.annotations.VisibleForTesting;
 
@@ -46,20 +45,17 @@ public class CommandUtil {
     return "DROP ROLE " + roleName;
   }
 
-  public static String createCmdForRoleAddGroup(
-      TAlterSentryRoleAddGroupsRequest request) {
-    return createCmdForRoleAddOrDeleteGroup(request.getRoleName(),
-        request.getGroupsIterator(), true);
+  public static String createCmdForRoleAddGroup(String roleName, String 
groups) {
+    return createCmdForRoleAddOrDeleteGroup(roleName, groups, true);
   }
 
-  public static String createCmdForRoleDeleteGroup(
-      TAlterSentryRoleDeleteGroupsRequest request) {
-    return createCmdForRoleAddOrDeleteGroup(request.getRoleName(),
-        request.getGroupsIterator(), false);
+  public static String createCmdForRoleDeleteGroup(String roleName, String 
groups) {
+    return createCmdForRoleAddOrDeleteGroup(roleName, groups, false);
   }
 
   private static String createCmdForRoleAddOrDeleteGroup(String roleName,
-      Iterator<TSentryGroup> iter, boolean isAddGroup) {
+ String groups,
+      boolean isAddGroup) {
     StringBuilder sb = new StringBuilder();
     if (isAddGroup) {
       sb.append("GRANT ROLE ");
@@ -73,17 +69,8 @@ public class CommandUtil {
       sb.append(" FROM ");
     }
 
-    if (iter != null) {
-      sb.append("GROUP ");
-      boolean commaFlg = false;
-      while (iter.hasNext()) {
-        if (commaFlg) {
-          sb.append(", ");
-        } else {
-          commaFlg = true;
-        }
-        sb.append(iter.next().getGroupName());
-      }
+    if (!StringUtils.isEmpty(groups)) {
+      sb.append("GROUP ").append(groups);
     } else {
       sb = new StringBuilder("Missing group information.");
     }
@@ -159,6 +146,60 @@ public class CommandUtil {
     return sb.toString();
   }
 
+  public static String createCmdForGrantGMPrivilege(
+      
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest
 request) {
+    return createCmdForGrantOrRevokeGMPrivilege(request.getRoleName(), 
request.getPrivilege(), true);
+  }
+
+  public static String createCmdForRevokeGMPrivilege(
+      
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest
 request) {
+    return createCmdForGrantOrRevokeGMPrivilege(request.getRoleName(), 
request.getPrivilege(),
+        false);
+  }
+
+  private static String createCmdForGrantOrRevokeGMPrivilege(String roleName,
+      org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege 
privilege,
+      boolean isGrant) {
+    StringBuilder sb = new StringBuilder();
+    if (isGrant) {
+      sb.append("GRANT ");
+    } else {
+      sb.append("REVOKE ");
+    }
+
+    String action = privilege.getAction();
+    if (AccessConstants.ALL.equalsIgnoreCase(action)) {
+      sb.append("ALL");
+    } else {
+      if (action != null) {
+        action = action.toUpperCase();
+      }
+      sb.append(action);
+    }
+
+    sb.append(" ON");
+
+    List<TAuthorizable> authorizables = privilege.getAuthorizables();
+    if (authorizables != null) {
+      for (TAuthorizable authorizable : authorizables) {
+        sb.append(" ").append(authorizable.getType()).append(" 
").append(authorizable.getName());
+      }
+    }
+
+    if (isGrant) {
+      sb.append(" TO ROLE ");
+    } else {
+      sb.append(" FROM ROLE ");
+    }
+    sb.append(roleName);
+
+    if (privilege.getGrantOption() == 
org.apache.sentry.provider.db.generic.service.thrift.TSentryGrantOption.TRUE) {
+      sb.append(" WITH GRANT OPTION");
+    }
+
+    return sb.toString();
+  }
+
   // Check if the given IP is one of the local IP.
   @VisibleForTesting
   public static boolean assertIPInAuditLog(String ipInAuditLog) throws 
Exception {

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java
index 072a0e8..b0a87ae 100644
--- 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java
@@ -30,6 +30,7 @@ import 
org.apache.sentry.provider.db.service.thrift.TDropSentryRoleRequest;
 
 public class Constants {
   public final static String AUDIT_LOGGER_NAME = 
"sentry.hive.authorization.ddl.logger";
+  public final static String AUDIT_LOGGER_NAME_GENERIC = 
"sentry.generic.authorization.ddl.logger";
 
   public final static String LOG_FIELD_SERVICE_NAME = "serviceName";
   public final static String LOG_FIELD_USER_NAME = "userName";
@@ -44,6 +45,7 @@ public class Constants {
   public final static String LOG_FIELD_COLUMN_NAME = "column";
   public final static String LOG_FIELD_RESOURCE_PATH = "resourcePath";
   public final static String LOG_FIELD_OBJECT_TYPE = "objectType";
+  public final static String LOG_FIELD_COMPONENT = "component";
 
   public final static String OPERATION_CREATE_ROLE = "CREATE_ROLE";
   public final static String OPERATION_DROP_ROLE = "DROP_ROLE";
@@ -62,6 +64,7 @@ public class Constants {
   public static final Map<String, String> requestTypeToObjectTypeMap = new 
HashMap<String, String>();
 
   static {
+    // for hive audit log
     requestTypeToOperationMap.put(TCreateSentryRoleRequest.class.getName(),
         Constants.OPERATION_CREATE_ROLE);
     requestTypeToOperationMap.put(
@@ -78,7 +81,30 @@ public class Constants {
     requestTypeToOperationMap.put(
         TAlterSentryRoleDeleteGroupsRequest.class.getName(),
         Constants.OPERATION_DELETE_ROLE);
+    // for generic model audit log
+    requestTypeToOperationMap.put(
+        
org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleRequest.class
+            .getName(), Constants.OPERATION_CREATE_ROLE);
+    requestTypeToOperationMap
+        
.put(org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleRequest.class
+            .getName(), Constants.OPERATION_DROP_ROLE);
+    requestTypeToOperationMap
+        .put(
+            
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest.class
+                .getName(), Constants.OPERATION_GRANT_PRIVILEGE);
+    requestTypeToOperationMap
+        .put(
+            
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest.class
+                .getName(), Constants.OPERATION_REVOKE_PRIVILEGE);
+    requestTypeToOperationMap.put(
+        
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsRequest.class
+            .getName(), Constants.OPERATION_ADD_ROLE);
+    requestTypeToOperationMap
+        .put(
+            
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsRequest.class
+                .getName(), Constants.OPERATION_DELETE_ROLE);
 
+    // for hive audit log
     requestTypeToObjectTypeMap.put(TCreateSentryRoleRequest.class.getName(),
         Constants.OBJECT_TYPE_ROLE);
     requestTypeToObjectTypeMap.put(TDropSentryRoleRequest.class.getName(),
@@ -95,5 +121,27 @@ public class Constants {
     requestTypeToObjectTypeMap.put(
         TAlterSentryRoleRevokePrivilegeRequest.class.getName(),
         Constants.OBJECT_TYPE_PRINCIPAL);
+    // for generic model audit log
+    requestTypeToObjectTypeMap.put(
+        
org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleRequest.class
+            .getName(), Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap
+        
.put(org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleRequest.class
+            .getName(), Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap.put(
+        
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsRequest.class
+            .getName(), Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap
+        .put(
+            
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsRequest.class
+                .getName(), Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap
+        .put(
+            
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest.class
+                .getName(), Constants.OBJECT_TYPE_PRINCIPAL);
+    requestTypeToObjectTypeMap
+        .put(
+            
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest.class
+                .getName(), Constants.OBJECT_TYPE_PRINCIPAL);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
index ea9fae9..4f8c834 100644
--- 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
@@ -249,8 +249,14 @@ public class SentryPolicyStoreProcessor implements 
SentryPolicyService.Iface {
       timerContext.stop();
     }
 
-    AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
-               request, response, conf).toJsonFormatLog());
+    try {
+      AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance()
+          .createJsonLogEntity(request, response, conf).toJsonFormatLog());
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for create role: " + 
e.getMessage();
+      LOGGER.error(msg, e);
+    }
     return response;
   }
 
@@ -305,10 +311,16 @@ public class SentryPolicyStoreProcessor implements 
SentryPolicyService.Iface {
       timerContext.stop();
     }
 
-    Set<JsonLogEntity> jsonLogEntitys = 
JsonLogEntityFactory.getInstance().createJsonLogEntitys(
-        request, response, conf);
-    for (JsonLogEntity jsonLogEntity : jsonLogEntitys) {
-      AUDIT_LOGGER.info(jsonLogEntity.toJsonFormatLog());
+    try {
+      Set<JsonLogEntity> jsonLogEntitys = 
JsonLogEntityFactory.getInstance().createJsonLogEntitys(
+          request, response, conf);
+      for (JsonLogEntity jsonLogEntity : jsonLogEntitys) {
+        AUDIT_LOGGER.info(jsonLogEntity.toJsonFormatLog());
+      }
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for grant privilege to role: " + 
e.getMessage();
+      LOGGER.error(msg, e);
     }
     return response;
   }
@@ -374,10 +386,16 @@ public class SentryPolicyStoreProcessor implements 
SentryPolicyService.Iface {
       timerContext.stop();
     }
 
-    Set<JsonLogEntity> jsonLogEntitys = 
JsonLogEntityFactory.getInstance().createJsonLogEntitys(
-        request, response, conf);
-    for (JsonLogEntity jsonLogEntity : jsonLogEntitys) {
-      AUDIT_LOGGER.info(jsonLogEntity.toJsonFormatLog());
+    try {
+      Set<JsonLogEntity> jsonLogEntitys = 
JsonLogEntityFactory.getInstance().createJsonLogEntitys(
+          request, response, conf);
+      for (JsonLogEntity jsonLogEntity : jsonLogEntitys) {
+        AUDIT_LOGGER.info(jsonLogEntity.toJsonFormatLog());
+      }
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for revoke privilege from role: " 
+ e.getMessage();
+      LOGGER.error(msg, e);
     }
     return response;
   }
@@ -417,8 +435,14 @@ public class SentryPolicyStoreProcessor implements 
SentryPolicyService.Iface {
       timerContext.stop();
     }
 
-    AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
-               request, response, conf).toJsonFormatLog());
+    try {
+      AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance()
+          .createJsonLogEntity(request, response, conf).toJsonFormatLog());
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for drop role: " + e.getMessage();
+      LOGGER.error(msg, e);
+    }
     return response;
   }
 
@@ -457,8 +481,14 @@ public class SentryPolicyStoreProcessor implements 
SentryPolicyService.Iface {
       timerContext.stop();
     }
 
-    AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
-               request, response, conf).toJsonFormatLog());
+    try {
+      AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance()
+          .createJsonLogEntity(request, response, conf).toJsonFormatLog());
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for add role to group: " + 
e.getMessage();
+      LOGGER.error(msg, e);
+    }
     return response;
   }
 
@@ -497,8 +527,14 @@ public class SentryPolicyStoreProcessor implements 
SentryPolicyService.Iface {
       timerContext.stop();
     }
 
-    AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
-               request, response, conf).toJsonFormatLog());
+    try {
+      AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance()
+          .createJsonLogEntity(request, response, conf).toJsonFormatLog());
+    } catch (Exception e) {
+      // if any exception, log the exception.
+      String msg = "Error creating audit log for delete role from group: " + 
e.getMessage();
+      LOGGER.error(msg, e);
+    }
     return response;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestAuditLogForSentryGenericService.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestAuditLogForSentryGenericService.java
 
b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestAuditLogForSentryGenericService.java
new file mode 100644
index 0000000..c3adacf
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestAuditLogForSentryGenericService.java
@@ -0,0 +1,299 @@
+/**
+ * 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.sentry.provider.db.generic.service.thrift;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.sentry.provider.db.log.appender.AuditLoggerTestAppender;
+import org.apache.sentry.provider.db.log.util.CommandUtil;
+import org.apache.sentry.provider.db.log.util.Constants;
+import org.apache.sentry.service.thrift.SentryServiceIntegrationBase;
+import org.codehaus.jettison.json.JSONObject;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+public class TestAuditLogForSentryGenericService extends 
SentryServiceIntegrationBase {
+
+  private SentryGenericServiceClient client;
+  private static final String COMPONENT = "SQOOP";
+  private static final org.slf4j.Logger LOGGER = LoggerFactory
+      .getLogger(TestAuditLogForSentryGenericService.class);
+
+  @BeforeClass
+  public static void setup() throws Exception {
+    SentryServiceIntegrationBase.setup();
+    Logger logger = 
Logger.getLogger("sentry.generic.authorization.ddl.logger");
+    AuditLoggerTestAppender testAppender = new AuditLoggerTestAppender();
+    logger.addAppender(testAppender);
+    logger.setLevel(Level.INFO);
+  }
+
+  @Override
+  @After
+  public void after() {
+    try {
+      runTestAsSubject(new TestOperation() {
+        @Override
+        public void runTestAsSubject() throws Exception {
+          Set<TSentryRole> tRoles = client.listAllRoles(ADMIN_USER, COMPONENT);
+          for (TSentryRole tRole : tRoles) {
+            client.dropRole(ADMIN_USER, tRole.getRoleName(), COMPONENT);
+          }
+          if (client != null) {
+            client.close();
+          }
+        }
+      });
+    } catch (Exception e) {
+      // log the exception
+      LOGGER.warn("Exception happened after test case.", e);
+    } finally {
+      policyFilePath.delete();
+    }
+  }
+
+  /**
+   * use the generic client to connect sentry service
+   */
+  @Override
+  public void connectToSentryService() throws Exception {
+    if (kerberos) {
+      this.client = Subject.doAs(clientSubject,
+          new PrivilegedExceptionAction<SentryGenericServiceClient>() {
+            @Override
+            public SentryGenericServiceClient run() throws Exception {
+              return SentryGenericServiceClientFactory.create(conf);
+            }
+          });
+    } else {
+      this.client = SentryGenericServiceClientFactory.create(conf);
+    }
+  }
+
+  @Test
+  public void testAuditLogForGenericModel() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String requestorUserName = ADMIN_USER;
+        Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+        String roleName = "admin_r";
+        String testGroupName = "g1";
+        String action = "all";
+        String service = "sentryService";
+        setLocalGroupMapping(requestorUserName, requestorUserGroupNames);
+        writePolicyFile();
+
+        // test the audit log for create role, success
+        client.createRole(requestorUserName, roleName, COMPONENT);
+        Map<String, String> fieldValueMap = new HashMap<String, String>();
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_CREATE_ROLE);
+        fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "CREATE ROLE " + 
roleName);
+        fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE);
+        fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+        assertAuditLog(fieldValueMap);
+
+        // test the audit log for create role, failed
+        try {
+          client.createRole(requestorUserName, roleName, COMPONENT);
+          fail("Exception should have been thrown");
+        } catch (Exception e) {
+          fieldValueMap.clear();
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_CREATE_ROLE);
+          fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "CREATE ROLE " 
+ roleName);
+          fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE);
+          fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+          assertAuditLog(fieldValueMap);
+        }
+
+        // test the audit log for add role to group, success
+        client.addRoleToGroups(requestorUserName, roleName, COMPONENT,
+            Sets.newHashSet(testGroupName));
+        fieldValueMap.clear();
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_ADD_ROLE);
+        fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "GRANT ROLE " + 
roleName
+            + " TO GROUP " + testGroupName);
+        fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE);
+        fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+        assertAuditLog(fieldValueMap);
+
+        // test the audit log for add role to group, failed
+        try {
+          client.addRoleToGroups(requestorUserName, "invalidRole", COMPONENT,
+              Sets.newHashSet(testGroupName));
+          fail("Exception should have been thrown");
+        } catch (Exception e) {
+          fieldValueMap.clear();
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_ADD_ROLE);
+          fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "GRANT ROLE 
invalidRole TO GROUP "
+              + testGroupName);
+          fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE);
+          fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+          assertAuditLog(fieldValueMap);
+        }
+
+        // test the audit log for grant privilege, success
+        TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT, service, 
Lists.newArrayList(
+            new TAuthorizable("resourceType1", "resourceName1"), new 
TAuthorizable("resourceType2",
+                "resourceName2")), action);
+        client.grantPrivilege(requestorUserName, roleName, COMPONENT, 
privilege);
+        fieldValueMap.clear();
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_GRANT_PRIVILEGE);
+        fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT,
+            "GRANT ALL ON resourceType1 resourceName1 resourceType2 
resourceName2 TO ROLE "
+                + roleName);
+        fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE);
+        fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+        assertAuditLog(fieldValueMap);
+
+        // for error audit log
+        TSentryPrivilege invalidPrivilege = new TSentryPrivilege(COMPONENT, 
service,
+            Lists.newArrayList(new TAuthorizable("resourceType1", 
"resourceName1")),
+            "invalidAction");
+        // test the audit log for grant privilege, failed
+        try {
+          client.grantPrivilege(requestorUserName, roleName, COMPONENT, 
invalidPrivilege);
+          fail("Exception should have been thrown");
+        } catch (Exception e) {
+          fieldValueMap.clear();
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_GRANT_PRIVILEGE);
+          fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT,
+              "GRANT INVALIDACTION ON resourceType1 resourceName1 TO ROLE " + 
roleName);
+          fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE);
+          fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+          assertAuditLog(fieldValueMap);
+        }
+
+        // test the audit log for revoke privilege, success
+        client.revokePrivilege(requestorUserName, roleName, COMPONENT, 
privilege);
+        fieldValueMap.clear();
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_REVOKE_PRIVILEGE);
+        fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT,
+            "REVOKE ALL ON resourceType1 resourceName1 resourceType2 
resourceName2 FROM ROLE "
+                + roleName);
+        fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE);
+        fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+        assertAuditLog(fieldValueMap);
+
+        // test the audit log for revoke privilege, failed
+        try {
+          client.revokePrivilege(requestorUserName, "invalidRole", COMPONENT, 
invalidPrivilege);
+          fail("Exception should have been thrown");
+        } catch (Exception e) {
+          fieldValueMap.clear();
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_REVOKE_PRIVILEGE);
+          fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT,
+              "REVOKE INVALIDACTION ON resourceType1 resourceName1 FROM ROLE 
invalidRole");
+          fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE);
+          fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+          assertAuditLog(fieldValueMap);
+        }
+
+        // test the audit log for delete role from group, success
+        client.deleteRoleToGroups(requestorUserName, roleName, COMPONENT,
+            Sets.newHashSet(testGroupName));
+        fieldValueMap.clear();
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_DELETE_ROLE);
+        fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "REVOKE ROLE " + 
roleName
+            + " FROM GROUP " + testGroupName);
+        fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE);
+        fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+        assertAuditLog(fieldValueMap);
+        // test the audit log for delete role from group, failed
+        try {
+          client.deleteRoleToGroups(requestorUserName, "invalidRole", 
COMPONENT,
+              Sets.newHashSet(testGroupName));
+          fail("Exception should have been thrown");
+        } catch (Exception e) {
+          fieldValueMap.clear();
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_DELETE_ROLE);
+          fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT,
+              "REVOKE ROLE invalidRole FROM GROUP " + testGroupName);
+          fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE);
+          fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+          assertAuditLog(fieldValueMap);
+        }
+        // test the audit log for drop role, success
+        client.dropRole(requestorUserName, roleName, COMPONENT);
+        fieldValueMap.clear();
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_DROP_ROLE);
+        fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+        fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "DROP ROLE " + 
roleName);
+        fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE);
+        fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+        assertAuditLog(fieldValueMap);
+        // test the audit log for drop role, failed
+        try {
+          client.dropRole(requestorUserName, roleName, COMPONENT);
+          fail("Exception should have been thrown");
+        } catch (Exception e) {
+          fieldValueMap.clear();
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION, 
Constants.OPERATION_DROP_ROLE);
+          fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT);
+          fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "DROP ROLE " + 
roleName);
+          fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE);
+          fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null);
+          assertAuditLog(fieldValueMap);
+        }
+      }
+    });
+  }
+
+  private void assertAuditLog(Map<String, String> fieldValueMap) throws 
Exception {
+    assertThat(AuditLoggerTestAppender.getLastLogLevel(), is(Level.INFO));
+    JSONObject jsonObject = new 
JSONObject(AuditLoggerTestAppender.getLastLogEvent());
+    if (fieldValueMap != null) {
+      for (Map.Entry<String, String> entry : fieldValueMap.entrySet()) {
+        String entryKey = entry.getKey();
+        if (Constants.LOG_FIELD_IP_ADDRESS.equals(entryKey)) {
+          
assertTrue(CommandUtil.assertIPInAuditLog(jsonObject.get(entryKey).toString()));
+        } else {
+          
assertTrue(entry.getValue().equalsIgnoreCase(jsonObject.get(entryKey).toString()));
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestAuditMetadataLogEntity.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestAuditMetadataLogEntity.java
 
b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestAuditMetadataLogEntity.java
deleted file mode 100644
index 95b51e9..0000000
--- 
a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestAuditMetadataLogEntity.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * 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.sentry.provider.db.log.entity;
-
-import junit.framework.TestCase;
-
-import org.apache.sentry.provider.db.log.util.Constants;
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.node.ContainerNode;
-import org.junit.Test;
-
-public class TestAuditMetadataLogEntity extends TestCase {
-
-  @Test
-  public void testToJsonFormatLog() throws Throwable {
-    AuditMetadataLogEntity amle = new AuditMetadataLogEntity("serviceName",
-        "userName", "impersonator", "ipAddress", "operation", "eventTime",
-        "operationText", "allowed", "databaseName", "tableName", "columnName",
-        "resourcePath", "objectType");
-    String jsonAuditLog = amle.toJsonFormatLog();
-    ContainerNode rootNode = AuditMetadataLogEntity.parse(jsonAuditLog);
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_SERVICE_NAME, 
"serviceName");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_USER_NAME, "userName");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_IMPERSONATOR,
-        "impersonator");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_IP_ADDRESS, "ipAddress");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_OPERATION, "operation");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_EVENT_TIME, "eventTime");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_OPERATION_TEXT,
-        "operationText");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_ALLOWED, "allowed");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_DATABASE_NAME,
-        "databaseName");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_TABLE_NAME, "tableName");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_COLUMN_NAME, "columnName");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_RESOURCE_PATH,
-        "resourcePath");
-    assertEntryEquals(rootNode, Constants.LOG_FIELD_OBJECT_TYPE, "objectType");
-  }
-
-  void assertEntryEquals(ContainerNode rootNode, String key, String value) {
-    JsonNode node = assertNodeContains(rootNode, key);
-    assertEquals(value, node.getTextValue());
-  }
-
-  private JsonNode assertNodeContains(ContainerNode rootNode, String key) {
-    JsonNode node = rootNode.get(key);
-    if (node == null) {
-      fail("No entry of name \"" + key + "\" found in " + rootNode.toString());
-    }
-    return node;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestDbAuditMetadataLogEntity.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestDbAuditMetadataLogEntity.java
 
b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestDbAuditMetadataLogEntity.java
new file mode 100644
index 0000000..e3ba541
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestDbAuditMetadataLogEntity.java
@@ -0,0 +1,69 @@
+/**
+ * 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.sentry.provider.db.log.entity;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.fail;
+
+import org.apache.sentry.provider.db.log.util.Constants;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.node.ContainerNode;
+import org.junit.Test;
+
+public class TestDbAuditMetadataLogEntity {
+
+  @Test
+  public void testToJsonFormatLog() throws Throwable {
+    DBAuditMetadataLogEntity amle = new 
DBAuditMetadataLogEntity("serviceName", "userName",
+        "impersonator", "ipAddress", "operation", "eventTime", 
"operationText", "allowed",
+        "objectType", "component", "databaseName", "tableName", "columnName", 
"resourcePath");
+    String jsonAuditLog = amle.toJsonFormatLog();
+    ContainerNode rootNode = AuditMetadataLogEntity.parse(jsonAuditLog);
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_SERVICE_NAME, 
"serviceName");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_USER_NAME, "userName");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_IMPERSONATOR,
+        "impersonator");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_IP_ADDRESS, "ipAddress");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_OPERATION, "operation");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_EVENT_TIME, "eventTime");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_OPERATION_TEXT,
+        "operationText");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_ALLOWED, "allowed");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_DATABASE_NAME,
+        "databaseName");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_TABLE_NAME, "tableName");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_COLUMN_NAME, "columnName");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_RESOURCE_PATH,
+        "resourcePath");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_OBJECT_TYPE, "objectType");
+  }
+
+  void assertEntryEquals(ContainerNode rootNode, String key, String value) {
+    JsonNode node = assertNodeContains(rootNode, key);
+    assertEquals(value, node.getTextValue());
+  }
+
+  private JsonNode assertNodeContains(ContainerNode rootNode, String key) {
+    JsonNode node = rootNode.get(key);
+    if (node == null) {
+      fail("No entry of name \"" + key + "\" found in " + rootNode.toString());
+    }
+    return node;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/66b7096c/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestGMAuditMetadataLogEntity.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestGMAuditMetadataLogEntity.java
 
b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestGMAuditMetadataLogEntity.java
new file mode 100644
index 0000000..537edb4
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/entity/TestGMAuditMetadataLogEntity.java
@@ -0,0 +1,74 @@
+/**
+ * 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.sentry.provider.db.log.entity;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.fail;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sentry.provider.db.log.util.Constants;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.node.ContainerNode;
+import org.junit.Test;
+
+public class TestGMAuditMetadataLogEntity {
+  @Test
+  public void testToJsonFormatLog() throws Throwable {
+
+    Map<String, String> privilegesMap = new HashMap<String, String>();
+    privilegesMap.put("resourceType1", "resourceName1");
+    privilegesMap.put("resourceType2", "resourceName2");
+    privilegesMap.put("resourceType3", "resourceName3");
+    privilegesMap.put("resourceType4", "resourceName4");
+    GMAuditMetadataLogEntity gmamle = new 
GMAuditMetadataLogEntity("serviceName", "userName",
+        "impersonator", "ipAddress", "operation", "eventTime", 
"operationText", "allowed",
+        "objectType", "component", privilegesMap);
+    String jsonAuditLog = gmamle.toJsonFormatLog();
+    ContainerNode rootNode = AuditMetadataLogEntity.parse(jsonAuditLog);
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_SERVICE_NAME, 
"serviceName");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_USER_NAME, "userName");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_IMPERSONATOR, 
"impersonator");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_IP_ADDRESS, "ipAddress");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_OPERATION, "operation");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_EVENT_TIME, "eventTime");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_OPERATION_TEXT, 
"operationText");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_ALLOWED, "allowed");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_OBJECT_TYPE, "objectType");
+    assertEntryEquals(rootNode, Constants.LOG_FIELD_COMPONENT, "component");
+    assertEntryEquals(rootNode, "resourceType1", "resourceName1");
+    assertEntryEquals(rootNode, "resourceType2", "resourceName2");
+    assertEntryEquals(rootNode, "resourceType3", "resourceName3");
+    assertEntryEquals(rootNode, "resourceType4", "resourceName4");
+  }
+
+  void assertEntryEquals(ContainerNode rootNode, String key, String value) {
+    JsonNode node = assertNodeContains(rootNode, key);
+    assertEquals(value, node.getTextValue());
+  }
+
+  private JsonNode assertNodeContains(ContainerNode rootNode, String key) {
+    JsonNode node = rootNode.get(key);
+    if (node == null) {
+      fail("No entry of name \"" + key + "\" found in " + rootNode.toString());
+    }
+    return node;
+  }
+}

Reply via email to