sentry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sp...@apache.org
Subject [61/86] sentry git commit: SENTRY-2208: Refactor out Sentry service into own module from sentry-provider-db (Anthony Young-Garner, reviewed by Sergio Pena, Steve Moist, Na Li)
Date Thu, 31 May 2018 03:32:39 GMT
http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/GMAuditMetadataLogEntity.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/GMAuditMetadataLogEntity.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/GMAuditMetadataLogEntity.java
new file mode 100644
index 0000000..6911772
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/GMAuditMetadataLogEntity.java
@@ -0,0 +1,97 @@
+/**
+ * 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, getServiceName());
+      json.writeStringField(Constants.LOG_FIELD_USER_NAME, getUserName());
+      json.writeStringField(Constants.LOG_FIELD_IMPERSONATOR, getImpersonator());
+      json.writeStringField(Constants.LOG_FIELD_IP_ADDRESS, getIpAddress());
+      json.writeStringField(Constants.LOG_FIELD_OPERATION, getOperation());
+      json.writeStringField(Constants.LOG_FIELD_EVENT_TIME, getEventTime());
+      json.writeStringField(Constants.LOG_FIELD_OPERATION_TEXT, getOperationText());
+      json.writeStringField(Constants.LOG_FIELD_ALLOWED, getAllowed());
+      for (Map.Entry<String, String> entry : privilegesMap.entrySet()) {
+        json.writeStringField(entry.getKey(), entry.getValue());
+      }
+      json.writeStringField(Constants.LOG_FIELD_OBJECT_TYPE, getObjectType());
+      json.writeStringField(Constants.LOG_FIELD_COMPONENT, getComponent());
+      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) {
+        String msg = "Error when close json object: " + e.getMessage();
+        LOGGER.error(msg, 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/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntity.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntity.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntity.java
new file mode 100644
index 0000000..913f125
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntity.java
@@ -0,0 +1,25 @@
+/**
+ * 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;
+
+public interface JsonLogEntity {
+
+  String toJsonFormatLog() throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntityFactory.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntityFactory.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntityFactory.java
new file mode 100644
index 0000000..61becce
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/entity/JsonLogEntityFactory.java
@@ -0,0 +1,351 @@
+/**
+ * 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.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.api.generic.thrift.TAuthorizable;
+import org.apache.sentry.provider.db.log.util.CommandUtil;
+import org.apache.sentry.provider.db.log.util.Constants;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleAddGroupsRequest;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleAddGroupsResponse;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleAddUsersRequest;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleAddUsersResponse;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleDeleteGroupsRequest;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleDeleteGroupsResponse;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleDeleteUsersRequest;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleDeleteUsersResponse;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleGrantPrivilegeRequest;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleGrantPrivilegeResponse;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleRevokePrivilegeRequest;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleRevokePrivilegeResponse;
+import org.apache.sentry.api.service.thrift.TCreateSentryRoleRequest;
+import org.apache.sentry.api.service.thrift.TCreateSentryRoleResponse;
+import org.apache.sentry.api.service.thrift.TDropSentryRoleRequest;
+import org.apache.sentry.api.service.thrift.TDropSentryRoleResponse;
+import org.apache.sentry.api.service.thrift.TSentryGroup;
+import org.apache.sentry.api.service.thrift.TSentryPrivilege;
+import org.apache.sentry.core.common.utils.ThriftUtil;
+import org.apache.sentry.service.common.ServiceConstants.ServerConfig;
+import org.apache.sentry.api.common.Status;
+import org.apache.sentry.service.thrift.TSentryResponseStatus;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableSet;
+
+public final class JsonLogEntityFactory {
+
+  private static JsonLogEntityFactory factory = new JsonLogEntityFactory();
+
+  private JsonLogEntityFactory() {
+  }
+
+  public static JsonLogEntityFactory getInstance() {
+    return factory;
+  }
+
+  // log entity for hive/impala create role
+  public JsonLogEntity createJsonLogEntity(TCreateSentryRoleRequest request,
+      TCreateSentryRoleResponse response, Configuration conf) {
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName());
+    hamle.setOperationText(CommandUtil.createCmdForCreateOrDropRole(
+        request.getRoleName(), true));
+
+    return hamle;
+  }
+
+  // log entity for hive/impala drop role
+  public JsonLogEntity createJsonLogEntity(TDropSentryRoleRequest request,
+      TDropSentryRoleResponse response, Configuration conf) {
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName());
+    hamle.setOperationText(CommandUtil.createCmdForCreateOrDropRole(
+        request.getRoleName(), false));
+
+    return hamle;
+  }
+
+  // log entity for hive/impala grant privilege
+  public Set<JsonLogEntity> createJsonLogEntitys(
+      TAlterSentryRoleGrantPrivilegeRequest request,
+      TAlterSentryRoleGrantPrivilegeResponse response, Configuration conf) {
+    ImmutableSet.Builder<JsonLogEntity> setBuilder = ImmutableSet.builder();
+    if (request.isSetPrivileges()) {
+      for (TSentryPrivilege privilege : request.getPrivileges()) {
+        JsonLogEntity logEntity = createJsonLogEntity(request, privilege, response, conf);
+        setBuilder.add(logEntity);
+      }
+    }
+    return setBuilder.build();
+  }
+
+  private JsonLogEntity createJsonLogEntity(
+      TAlterSentryRoleGrantPrivilegeRequest request, TSentryPrivilege privilege,
+      TAlterSentryRoleGrantPrivilegeResponse response, Configuration conf) {
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName());
+    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) {
+    ImmutableSet.Builder<JsonLogEntity> setBuilder = ImmutableSet.builder();
+    if (request.isSetPrivileges()) {
+      for (TSentryPrivilege privilege : request.getPrivileges()) {
+        JsonLogEntity logEntity = createJsonLogEntity(request, privilege, response, conf);
+        setBuilder.add(logEntity);
+      }
+    }
+    return setBuilder.build();
+  }
+
+  private JsonLogEntity createJsonLogEntity(
+      TAlterSentryRoleRevokePrivilegeRequest request, TSentryPrivilege privilege,
+      TAlterSentryRoleRevokePrivilegeResponse response, Configuration conf) {
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName());
+    hamle.setOperationText(CommandUtil.createCmdForRevokePrivilege(request));
+    hamle.setDatabaseName(privilege.getDbName());
+    hamle.setTableName(privilege.getTableName());
+    hamle.setResourcePath(privilege.getURI());
+
+    return hamle;
+  }
+
+  // log entity for hive/impala add role to group
+  public JsonLogEntity createJsonLogEntity(
+      TAlterSentryRoleAddGroupsRequest request,
+      TAlterSentryRoleAddGroupsResponse response, Configuration conf) {
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName());
+    String groups = getGroupsStr(request.getGroupsIterator());
+    hamle.setOperationText(CommandUtil.createCmdForRoleAddGroup(request.getRoleName(), groups));
+
+    return hamle;
+  }
+
+  // log entity for hive/impala delete role from group
+  public JsonLogEntity createJsonLogEntity(
+      TAlterSentryRoleDeleteGroupsRequest request,
+      TAlterSentryRoleDeleteGroupsResponse response, Configuration conf) {
+    DBAuditMetadataLogEntity hamle = createCommonHAMLE(conf, response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName());
+    String groups = getGroupsStr(request.getGroupsIterator());
+    hamle.setOperationText(CommandUtil.createCmdForRoleDeleteGroup(request.getRoleName(), groups));
+
+    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 JsonLogEntity createJsonLogEntity(TAlterSentryRoleAddUsersRequest request,
+      TAlterSentryRoleAddUsersResponse response, Configuration conf) {
+    AuditMetadataLogEntity amle = createCommonHAMLE(conf, response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName());
+    String users = getUsersStr(request.getUsersIterator());
+    amle.setOperationText(CommandUtil.createCmdForRoleAddUser(request.getRoleName(), users));
+
+    return amle;
+  }
+
+  public JsonLogEntity createJsonLogEntity(TAlterSentryRoleDeleteUsersRequest request,
+      TAlterSentryRoleDeleteUsersResponse response, Configuration conf) {
+    AuditMetadataLogEntity amle = createCommonHAMLE(conf, response.getStatus(),
+        request.getRequestorUserName(), request.getClass().getName());
+    String users = getUsersStr(request.getUsersIterator());
+    amle.setOperationText(CommandUtil.createCmdForRoleDeleteUser(request.getRoleName(), users));
+
+    return amle;
+  }
+
+  private String getUsersStr(Iterator<String> iter) {
+    StringBuilder users = new StringBuilder("");
+    if (iter != null) {
+      boolean commaFlg = false;
+      while (iter.hasNext()) {
+        if (commaFlg) {
+          users.append(", ");
+        } else {
+          commaFlg = true;
+        }
+        users.append(iter.next());
+      }
+    }
+    return users.toString();
+  }
+
+  public String isAllowed(TSentryResponseStatus status) {
+    if (status.equals(Status.OK())) {
+      return Constants.TRUE;
+    }
+    return Constants.FALSE;
+  }
+
+  // log entity for generic model create role
+  public JsonLogEntity createJsonLogEntity(
+      org.apache.sentry.api.generic.thrift.TCreateSentryRoleRequest request,
+      org.apache.sentry.api.generic.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.api.generic.thrift.TDropSentryRoleRequest request,
+      org.apache.sentry.api.generic.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.api.generic.thrift.TAlterSentryRoleGrantPrivilegeRequest request,
+      org.apache.sentry.api.generic.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.api.generic.thrift.TAlterSentryRoleRevokePrivilegeRequest request,
+      org.apache.sentry.api.generic.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.api.generic.thrift.TAlterSentryRoleAddGroupsRequest request,
+      org.apache.sentry.api.generic.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.api.generic.thrift.TAlterSentryRoleDeleteGroupsRequest request,
+      org.apache.sentry.api.generic.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());
+    amle.setImpersonator(ThriftUtil.getImpersonator());
+    amle.setIpAddress(ThriftUtil.getIpAddress());
+    amle.setOperation(Constants.requestTypeToOperationMap.get(requestClassName));
+    amle.setEventTime(Long.toString(System.currentTimeMillis()));
+    amle.setAllowed(isAllowed(responseStatus));
+    amle.setObjectType(Constants.requestTypeToObjectTypeMap
+        .get(requestClassName));
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java
new file mode 100644
index 0000000..6479a60
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java
@@ -0,0 +1,233 @@
+/**
+ * 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.util;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.sentry.core.model.db.AccessConstants;
+import org.apache.sentry.api.generic.thrift.TAuthorizable;
+import org.apache.sentry.api.common.ApiConstants.PrivilegeScope;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleGrantPrivilegeRequest;
+import org.apache.sentry.api.service.thrift.TAlterSentryRoleRevokePrivilegeRequest;
+import org.apache.sentry.api.service.thrift.TSentryGrantOption;
+import org.apache.sentry.api.service.thrift.TSentryPrivilege;
+import org.datanucleus.util.StringUtils;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public final class CommandUtil {
+    
+  public CommandUtil() {
+    // Make constructor private to avoid instantiation
+  }
+
+  public static String createCmdForCreateOrDropRole(String roleName,
+      boolean isCreate) {
+    if (isCreate) {
+      return "CREATE ROLE " + roleName;
+    }
+    return "DROP ROLE " + roleName;
+  }
+
+  public static String createCmdForRoleAddGroup(String roleName, String groups) {
+    return createCmdForRoleGrant(roleName, groups, true, true);
+  }
+
+  public static String createCmdForRoleDeleteGroup(String roleName, String groups) {
+    return createCmdForRoleGrant(roleName, groups, false, true);
+  }
+
+  private static String createCmdForRoleGrant(String roleName, String principals,
+      boolean isGrant, boolean isGroup) {
+    StringBuilder sb = new StringBuilder();
+    if (isGrant) {
+      sb.append("GRANT ROLE ");
+    } else {
+      sb.append("REVOKE ROLE ");
+    }
+    sb.append(roleName);
+    if (isGrant) {
+      sb.append(" TO ");
+    } else {
+      sb.append(" FROM ");
+    }
+
+    String principalType = isGroup ? "GROUP" : "USER";
+    if (!StringUtils.isEmpty(principals)) {
+      sb.append(principalType).append(" ").append(principals);
+    } else {
+      sb = new StringBuilder("Missing " + principalType + " information.");
+    }
+
+    return sb.toString();
+  }
+
+  public static String createCmdForRoleAddUser(String roleName, String users) {
+    return createCmdForRoleGrant(roleName, users, true, false);
+  }
+
+  public static String createCmdForRoleDeleteUser(String roleName, String users) {
+    return createCmdForRoleGrant(roleName, users, false, false);
+  }
+
+  public static String createCmdForGrantPrivilege(
+      TAlterSentryRoleGrantPrivilegeRequest request) {
+    return createCmdForGrantOrRevokePrivileges(request.getRoleName(),
+        request.getPrivileges(), true);
+  }
+
+  public static String createCmdForRevokePrivilege(
+      TAlterSentryRoleRevokePrivilegeRequest request) {
+    return createCmdForGrantOrRevokePrivileges(request.getRoleName(),
+        request.getPrivileges(), false);
+  }
+
+  private static String createCmdForGrantOrRevokePrivileges(String roleName,
+      Set<TSentryPrivilege> privileges, boolean isGrant) {
+    StringBuilder sb = new StringBuilder();
+    if (privileges != null) {
+      for (TSentryPrivilege privilege : privileges) {
+        sb.append(createCmdForGrantOrRevokePrivilege(roleName, privilege, isGrant));
+      }
+    }
+    return sb.toString();
+  }
+
+  private static String createCmdForGrantOrRevokePrivilege(String roleName,
+      TSentryPrivilege privilege, boolean isGrant) {
+    StringBuilder sb = new StringBuilder();
+    if (isGrant) {
+      sb.append("GRANT ");
+    } else {
+      sb.append("REVOKE ");
+    }
+
+    String action = privilege.getAction();
+    String privilegeScope = privilege.getPrivilegeScope();
+    if (AccessConstants.ALL.equalsIgnoreCase(action)) {
+      sb.append("ALL");
+    } else {
+      if (action != null) {
+        action = action.toUpperCase();
+      }
+      sb.append(action);
+    }
+
+    sb.append(" ON ").append(privilege.getPrivilegeScope()).append(" ");
+    if (PrivilegeScope.DATABASE.name().equalsIgnoreCase(privilegeScope)) {
+      sb.append(privilege.getDbName());
+    } else if (PrivilegeScope.TABLE.name().equalsIgnoreCase(privilegeScope)) {
+      sb.append(privilege.getTableName());
+    } else if (PrivilegeScope.SERVER.name().equalsIgnoreCase(privilegeScope)) {
+      sb.append(privilege.getServerName());
+    } else if (PrivilegeScope.URI.name().equalsIgnoreCase(privilegeScope)) {
+      sb.append(privilege.getURI());
+    }
+
+    if (isGrant) {
+      sb.append(" TO ROLE ");
+    } else {
+      sb.append(" FROM ROLE ");
+    }
+    sb.append(roleName);
+
+    if (privilege.getGrantOption() == TSentryGrantOption.TRUE) {
+      sb.append(" WITH GRANT OPTION");
+    }
+
+    return sb.toString();
+  }
+
+  public static String createCmdForGrantGMPrivilege(
+      org.apache.sentry.api.generic.thrift.TAlterSentryRoleGrantPrivilegeRequest request) {
+    return createCmdForGrantOrRevokeGMPrivilege(request.getRoleName(), request.getPrivilege(), true);
+  }
+
+  public static String createCmdForRevokeGMPrivilege(
+      org.apache.sentry.api.generic.thrift.TAlterSentryRoleRevokePrivilegeRequest request) {
+    return createCmdForGrantOrRevokeGMPrivilege(request.getRoleName(), request.getPrivilege(),
+        false);
+  }
+
+  private static String createCmdForGrantOrRevokeGMPrivilege(String roleName,
+      org.apache.sentry.api.generic.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.api.generic.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 {
+    if (ipInAuditLog == null) {
+      return false;
+    }
+    Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
+    while (netInterfaces.hasMoreElements()) {
+      NetworkInterface ni = netInterfaces.nextElement();
+      Enumeration<InetAddress> ips = ni.getInetAddresses();
+      while (ips.hasMoreElements()) {
+        if (ipInAuditLog.indexOf(ips.nextElement().getHostAddress()) != -1) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java
new file mode 100644
index 0000000..6e91f8b
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java
@@ -0,0 +1,116 @@
+/**
+ * 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.util;
+
+import java.util.Map;
+import com.google.common.collect.ImmutableMap;
+
+import org.apache.sentry.api.service.thrift.*;
+
+public final class Constants {
+  public static final String AUDIT_LOGGER_NAME = "sentry.hive.authorization.ddl.logger";
+  public static final String AUDIT_LOGGER_NAME_GENERIC = "sentry.generic.authorization.ddl.logger";
+
+  public static final String LOG_FIELD_SERVICE_NAME = "serviceName";
+  public static final String LOG_FIELD_USER_NAME = "userName";
+  public static final String LOG_FIELD_IMPERSONATOR = "impersonator";
+  public static final String LOG_FIELD_IP_ADDRESS = "ipAddress";
+  public static final String LOG_FIELD_OPERATION = "operation";
+  public static final String LOG_FIELD_EVENT_TIME = "eventTime";
+  public static final String LOG_FIELD_OPERATION_TEXT = "operationText";
+  public static final String LOG_FIELD_ALLOWED = "allowed";
+  public static final String LOG_FIELD_DATABASE_NAME = "databaseName";
+  public static final String LOG_FIELD_TABLE_NAME = "tableName";
+  public static final String LOG_FIELD_COLUMN_NAME = "column";
+  public static final String LOG_FIELD_RESOURCE_PATH = "resourcePath";
+  public static final String LOG_FIELD_OBJECT_TYPE = "objectType";
+  public static final String LOG_FIELD_COMPONENT = "component";
+
+  public static final String OPERATION_CREATE_ROLE = "CREATE_ROLE";
+  public static final String OPERATION_DROP_ROLE = "DROP_ROLE";
+  public static final String OPERATION_ADD_ROLE = "ADD_ROLE_TO_GROUP";
+  public static final String OPERATION_DELETE_ROLE = "DELETE_ROLE_FROM_GROUP";
+  public static final String OPERATION_ADD_ROLE_USER = "ADD_ROLE_TO_USER";
+  public static final String OPERATION_DELETE_ROLE_USER = "DELETE_ROLE_FROM_USER";
+  public static final String OPERATION_GRANT_PRIVILEGE = "GRANT_PRIVILEGE";
+  public static final String OPERATION_REVOKE_PRIVILEGE = "REVOKE_PRIVILEGE";
+
+  public static final String OBJECT_TYPE_PRINCIPAL = "PRINCIPAL";
+  public static final String OBJECT_TYPE_ROLE = "ROLE";
+
+  public static final String TRUE = "true";
+  public static final String FALSE = "false";
+
+  public static final Map<String, String> requestTypeToOperationMap = ImmutableMap.<String, String>builder()
+    // for hive audit log
+    .put(TCreateSentryRoleRequest.class.getName(), Constants.OPERATION_CREATE_ROLE)
+    .put(TAlterSentryRoleGrantPrivilegeRequest.class.getName(), Constants.OPERATION_GRANT_PRIVILEGE)
+    .put(TAlterSentryRoleRevokePrivilegeRequest.class.getName(), Constants.OPERATION_REVOKE_PRIVILEGE)
+    .put(TDropSentryRoleRequest.class.getName(), Constants.OPERATION_DROP_ROLE)
+    .put(TAlterSentryRoleAddGroupsRequest.class.getName(), Constants.OPERATION_ADD_ROLE)
+    .put(TAlterSentryRoleDeleteGroupsRequest.class.getName(), Constants.OPERATION_DELETE_ROLE)
+    .put(TAlterSentryRoleAddUsersRequest.class.getName(), Constants.OPERATION_ADD_ROLE_USER)
+    .put(TAlterSentryRoleDeleteUsersRequest.class.getName(), Constants.OPERATION_DELETE_ROLE_USER)
+
+    // for generic model audit log
+    .put(org.apache.sentry.api.generic.thrift.TCreateSentryRoleRequest.class.getName(),
+        Constants.OPERATION_CREATE_ROLE)
+    .put(org.apache.sentry.api.generic.thrift.TDropSentryRoleRequest.class.getName(),
+        Constants.OPERATION_DROP_ROLE)
+    .put(org.apache.sentry.api.generic.thrift.TAlterSentryRoleGrantPrivilegeRequest.class.getName(),
+        Constants.OPERATION_GRANT_PRIVILEGE)
+    .put(org.apache.sentry.api.generic.thrift.TAlterSentryRoleRevokePrivilegeRequest.class.getName(),
+        Constants.OPERATION_REVOKE_PRIVILEGE)
+    .put(org.apache.sentry.api.generic.thrift.TAlterSentryRoleAddGroupsRequest.class.getName(),
+        Constants.OPERATION_ADD_ROLE)
+    .put(org.apache.sentry.api.generic.thrift.TAlterSentryRoleDeleteGroupsRequest.class.getName(),
+        Constants.OPERATION_DELETE_ROLE)
+    .build();
+  
+  public static final Map<String, String> requestTypeToObjectTypeMap = ImmutableMap.<String, String>builder()
+    // for hive audit log
+    .put(TCreateSentryRoleRequest.class.getName(), Constants.OBJECT_TYPE_ROLE)
+    .put(TDropSentryRoleRequest.class.getName(), Constants.OBJECT_TYPE_ROLE)
+    .put(TAlterSentryRoleAddGroupsRequest.class.getName(), Constants.OBJECT_TYPE_ROLE)
+    .put(TAlterSentryRoleDeleteGroupsRequest.class.getName(), Constants.OBJECT_TYPE_ROLE)
+    .put(TAlterSentryRoleAddUsersRequest.class.getName(), Constants.OBJECT_TYPE_ROLE)
+    .put(TAlterSentryRoleDeleteUsersRequest.class.getName(), Constants.OBJECT_TYPE_ROLE)
+    .put(TAlterSentryRoleGrantPrivilegeRequest.class.getName(), Constants.OBJECT_TYPE_PRINCIPAL)
+    .put(TAlterSentryRoleRevokePrivilegeRequest.class.getName(), Constants.OBJECT_TYPE_PRINCIPAL)
+
+    // for generic model audit log
+    .put(org.apache.sentry.api.generic.thrift.TCreateSentryRoleRequest.class.getName(),
+        Constants.OBJECT_TYPE_ROLE)
+    .put(org.apache.sentry.api.generic.thrift.TDropSentryRoleRequest.class.getName(),
+        Constants.OBJECT_TYPE_ROLE)
+    .put(org.apache.sentry.api.generic.thrift.TAlterSentryRoleAddGroupsRequest.class.getName(),
+        Constants.OBJECT_TYPE_ROLE)
+    .put(org.apache.sentry.api.generic.thrift.TAlterSentryRoleDeleteGroupsRequest.class.getName(),
+        Constants.OBJECT_TYPE_ROLE)
+    .put(org.apache.sentry.api.generic.thrift.TAlterSentryRoleGrantPrivilegeRequest.class.getName(),
+        Constants.OBJECT_TYPE_PRINCIPAL)
+    .put(org.apache.sentry.api.generic.thrift.TAlterSentryRoleRevokePrivilegeRequest.class.getName(),
+        Constants.OBJECT_TYPE_PRINCIPAL)
+    .build();
+
+  private Constants() {
+    // Make constructor private to avoid instantiation
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsMapping.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsMapping.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsMapping.java
new file mode 100644
index 0000000..c51f25a
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsMapping.java
@@ -0,0 +1,147 @@
+/**
+ * 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.service.model;
+
+import javax.jdo.annotations.PersistenceCapable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Transactional database backend for storing HMS Paths Updates. Any changes to this object
+ * require re-running the maven build so DN can re-enhance.
+ */
+@PersistenceCapable
+public class MAuthzPathsMapping {
+
+  private long authzSnapshotID;
+  private String authzObjName;
+  private Set<MPath> paths;
+  private long createTimeMs;
+
+  public MAuthzPathsMapping(long authzSnapshotID, String authzObjName, Collection<String> paths) {
+    this.authzSnapshotID = authzSnapshotID;
+    this.authzObjName = MSentryUtil.safeIntern(authzObjName);
+    this.paths = new HashSet<>(paths.size());
+    for (String path : paths) {
+      this.paths.add(new MPath(path));
+    }
+    this.createTimeMs = System.currentTimeMillis();
+  }
+
+  public long getCreateTime() {
+    return createTimeMs;
+  }
+
+  public void setCreateTime(long createTime) {
+    this.createTimeMs = createTime;
+  }
+
+  public String getAuthzObjName() {
+    return authzObjName;
+  }
+
+  public void setAuthzObjName(String authzObjName) {
+    this.authzObjName = authzObjName;
+  }
+
+  public void setPaths(Set<MPath> paths) {
+    this.paths = paths;
+  }
+
+  public Set<MPath> getPaths() {
+    return paths;
+  }
+
+  public boolean removePath(MPath path) {
+    return paths.remove(path);
+  }
+
+  public void addPath(MPath path) {
+    paths.add(path);
+  }
+
+  /**
+   * Gets MPath object that has the given path value.
+   * TODO: Try to avoid loop lookup in future for performance improvement.
+   *
+   * @param path the given path name
+   * @return an Path object that has the given path value.
+   */
+  public MPath getPath(String path) {
+    for (MPath mPath : paths) {
+      if (mPath.getPath().equals(path)) {
+        return mPath;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * @return collection of paths strings contained in this object.
+   */
+  public Collection<String> getPathStrings() {
+    Collection<String> pathValues = new ArrayList<>(this.paths.size());
+    for (MPath path : this.paths) {
+      pathValues.add(path.getPath());
+    }
+    return pathValues;
+  }
+
+  @Override
+  public String toString() {
+    return "MSentryPathsUpdate authzSnapshotID=[" + authzSnapshotID + "], authzObj=[" + authzObjName
+        + "], paths=[" + paths.toString() + "], createTimeMs=[" + createTimeMs + "]";
+  }
+
+  @Override
+  public int hashCode() {
+    return authzObjName == null ? 0 : authzObjName.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null) {
+      return false;
+    }
+
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+
+    MAuthzPathsMapping other = (MAuthzPathsMapping) obj;
+
+    if (authzObjName == null) {
+      if (other.authzObjName != null) {
+        return false;
+      }
+    } else if (!authzObjName.equals(other.authzObjName)) {
+      return false;
+    } else if (authzSnapshotID != other.authzSnapshotID) {
+      return false;
+   }
+
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsSnapshotId.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsSnapshotId.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsSnapshotId.java
new file mode 100644
index 0000000..d683c2c
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsSnapshotId.java
@@ -0,0 +1,63 @@
+/**
+ * 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.service.model;
+
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.PrimaryKey;
+
+/**
+ * This class is used to persist new authz paths snapshots IDs. An authz path snapshot ID is required by
+ * the MAuthzPathsMapping to detect new HMS snapshots created by the HMSFollower.
+ */
+@PersistenceCapable
+public class MAuthzPathsSnapshotId {
+  @PrimaryKey
+  private long authzSnapshotID;
+
+  public MAuthzPathsSnapshotId(long authzSnapshotID) {
+    this.authzSnapshotID = authzSnapshotID;
+  }
+
+  @Override
+  public String toString() {
+    return "MAuthzPathsSnapshotId authzSnapshotID=[" + authzSnapshotID + "]";
+  }
+
+  @Override
+  public int hashCode() {
+    return (int)authzSnapshotID;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null) {
+      return false;
+    }
+
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+
+    MAuthzPathsSnapshotId other = (MAuthzPathsSnapshotId) obj;
+    return (authzSnapshotID == other.authzSnapshotID);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MPath.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MPath.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MPath.java
new file mode 100644
index 0000000..b0eaff2
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MPath.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.service.model;
+
+/**
+ * Used to store the path for the Authorizable object
+ *
+ * New class is created for path in order to have 1 to many mapping
+ * between path and Authorizable object.
+ */
+public class MPath {
+  private String path;
+
+  public MPath(String path) {
+    this.path = MSentryUtil.safeIntern(path);
+  }
+
+  public String getPath() {
+    return path;
+  }
+
+  public void setPath(String path) { this.path = path; }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((path == null) ? 0 : path.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null) {
+      return false;
+    }
+
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+
+    MPath other = (MPath) obj;
+
+    if (path == null) {
+      return other.path == null;
+    }
+
+    return path.equals(other.path);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryChange.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryChange.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryChange.java
new file mode 100644
index 0000000..9b022a1
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryChange.java
@@ -0,0 +1,25 @@
+/**
+ * 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.service.model;
+
+/**
+ * The base class for various delta changes stored in Sentry DB.
+ */
+public interface MSentryChange {
+  long getChangeID();
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java
new file mode 100644
index 0000000..24ed204
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java
@@ -0,0 +1,436 @@
+/**
+ * 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.service.model;
+
+import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_JOINER;
+import static org.apache.sentry.core.common.utils.SentryConstants.KV_JOINER;
+
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.jdo.annotations.PersistenceCapable;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.core.model.db.AccessConstants;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+
+/**
+ * Database backed Sentry Generic Privilege for new authorization Model
+ * Any changes to this object
+ * require re-running the maven build so DN an re-enhance.
+ */
+@PersistenceCapable
+public class MSentryGMPrivilege {
+  public static final String PREFIX_RESOURCE_NAME = "resourceName";
+  public static final String PREFIX_RESOURCE_TYPE = "resourceType";
+  public static final int AUTHORIZABLE_LEVEL = 4;
+
+  private static final String NULL_COL = "__NULL__";
+  private static final String SERVICE_SCOPE = "Server";
+
+  /**
+   * The authorizable List has been stored into resourceName and resourceField columns
+   * We assume that the generic model privilege for any component(hive/impala or solr) doesn't exceed four level.
+   * This generic model privilege currently can support maximum 4 level.
+   **/
+  private String resourceName0 = NULL_COL; //NOPMD
+  private String resourceType0 = NULL_COL; //NOPMD
+  private String resourceName1 = NULL_COL; //NOPMD
+  private String resourceType1 = NULL_COL; //NOPMD
+  private String resourceName2 = NULL_COL; //NOPMD
+  private String resourceType2 = NULL_COL; //NOPMD
+  private String resourceName3 = NULL_COL; //NOPMD
+  private String resourceType3 = NULL_COL; //NOPMD
+
+
+  private String serviceName;
+  private String componentName;
+  private String action;
+  private String scope;
+
+  private Boolean grantOption = false;
+  // roles this privilege is a part of
+  private Set<MSentryRole> roles;
+  private long createTime;
+
+  public MSentryGMPrivilege() {
+    this.roles = new HashSet<MSentryRole>();
+  }
+
+  public MSentryGMPrivilege(String componentName, String serviceName,
+      List<? extends Authorizable> authorizables,
+      String action, Boolean grantOption) {
+    this.componentName = MSentryUtil.safeIntern(componentName);
+    this.serviceName = MSentryUtil.safeIntern(serviceName);
+    this.action = MSentryUtil.safeIntern(action);
+    this.grantOption = grantOption;
+    this.roles = new HashSet<>();
+    this.createTime = System.currentTimeMillis();
+    setAuthorizables(authorizables);
+  }
+
+  public MSentryGMPrivilege(MSentryGMPrivilege copy) {
+    this.action = copy.action;
+    this.componentName = copy.componentName;
+    this.serviceName = copy.serviceName;
+    this.grantOption = copy.grantOption;
+    this.scope = copy.scope;
+    this.createTime = copy.createTime;
+    setAuthorizables(copy.getAuthorizables());
+    this.roles = new HashSet<MSentryRole>();
+    roles.addAll(copy.roles);
+  }
+
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  public void setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+  public String getComponentName() {
+    return componentName;
+  }
+
+  public void setComponentName(String componentName) {
+    this.componentName = componentName;
+  }
+
+  public String getAction() {
+    return action;
+  }
+
+  public void setAction(String action) {
+    this.action = action;
+  }
+
+  public Boolean getGrantOption() {
+    return grantOption;
+  }
+
+  public void setGrantOption(Boolean grantOption) {
+    this.grantOption = grantOption;
+  }
+
+  public Set<MSentryRole> getRoles() {
+    return roles;
+  }
+
+  public void setRoles(Set<MSentryRole> roles) {
+    this.roles = roles;
+  }
+
+  public long getCreateTime() {
+    return createTime;
+  }
+
+  public void setCreateTime(long createTime) {
+    this.createTime = createTime;
+  }
+
+  public String getScope() {
+    return scope;
+  }
+
+  public List<? extends Authorizable> getAuthorizables() {
+    List<Authorizable> authorizables = Lists.newArrayList();
+    //construct atuhorizable lists
+    for (int i = 0; i < AUTHORIZABLE_LEVEL; i++) {
+      final String resourceName = (String) getField(this, PREFIX_RESOURCE_NAME + String.valueOf(i));
+      final String resourceTYpe = (String) getField(this, PREFIX_RESOURCE_TYPE + String.valueOf(i));
+
+      if (notNULL(resourceName) && notNULL(resourceTYpe)) {
+        authorizables.add(new Authorizable() {
+          @Override
+          public String getTypeName() {
+            return resourceTYpe;
+          }
+          @Override
+          public String getName() {
+            return resourceName;
+          }
+        });
+      }
+    }
+    return authorizables;
+  }
+
+  /**
+   * Only allow strict hierarchies. That is, can level =1 be not null when level = 0 is null
+   * @param authorizables
+   */
+  public void setAuthorizables(List<? extends Authorizable> authorizables) {
+    if (authorizables == null || authorizables.isEmpty()) {
+      //service scope
+      scope = SERVICE_SCOPE;
+      return;
+    }
+    if (authorizables.size() > AUTHORIZABLE_LEVEL) {
+      throw new IllegalStateException("This generic privilege model only supports maximum 4 level.");
+    }
+
+    for (int i = 0; i < authorizables.size(); i++) {
+      Authorizable authorizable = authorizables.get(i);
+      if (authorizable == null) {
+        String msg = String.format("The authorizable can't be null. Please check authorizables[%d]:", i);
+        throw new IllegalStateException(msg);
+      }
+      String resourceName = authorizable.getName();
+      String resourceTYpe = authorizable.getTypeName();
+      if (isNULL(resourceName) || isNULL(resourceTYpe)) {
+        String msg = String.format("The name and type of authorizable can't be empty or null.Please check authorizables[%d]", i);
+        throw new IllegalStateException(msg);
+      }
+      setField(this, PREFIX_RESOURCE_NAME + String.valueOf(i), toNULLCol(resourceName));
+      setField(this, PREFIX_RESOURCE_TYPE + String.valueOf(i), toNULLCol(resourceTYpe));
+      scope = resourceTYpe;
+    }
+  }
+
+  public void appendRole(MSentryRole role) {
+    if (roles.add(role)) {
+      role.appendGMPrivilege(this);
+    }
+  }
+
+  public void removeRole(MSentryRole role) {
+    if(roles.remove(role)) {
+      role.removeGMPrivilege(this);
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((action == null) ? 0 : action.hashCode());
+    result = prime * result + ((componentName == null) ? 0 : componentName.hashCode());
+    result = prime * result + ((serviceName == null) ? 0 : serviceName.hashCode());
+    result = prime * result + ((grantOption == null) ? 0 : grantOption.hashCode());
+    result = prime * result + ((scope == null) ? 0 : scope.hashCode());
+
+    for (Authorizable authorizable : getAuthorizables()) {
+      result = prime * result + authorizable.getName().hashCode();
+      result = prime * result + authorizable.getTypeName().hashCode();
+    }
+
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    List<String> unifiedNames = Lists.newArrayList();
+    for (Authorizable auth : getAuthorizables()) {
+      unifiedNames.add(KV_JOINER.join(auth.getTypeName(),auth.getName()));
+    }
+
+    return "MSentryGMPrivilege ["
+        + "serverName=" + serviceName + ", componentName=" + componentName
+        + ", authorizables=" + AUTHORIZABLE_JOINER.join(unifiedNames)+ ", scope=" + scope
+        + ", action=" + action + ", roles=[...]"  + ", createTime="
+        + createTime + ", grantOption=" + grantOption +"]";
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    MSentryGMPrivilege other = (MSentryGMPrivilege) obj;
+    if (action == null) {
+      if (other.action != null) {
+        return false;
+      }
+    } else if (!action.equalsIgnoreCase(other.action)) {
+      return false;
+    }
+    if (scope == null) {
+      if (other.scope != null) {
+        return false;
+      }
+    } else if (!scope.equals(other.scope)) {
+      return false;
+    }
+    if (serviceName == null) {
+      if (other.serviceName != null) {
+        return false;
+      }
+    } else if (!serviceName.equals(other.serviceName)) {
+      return false;
+    }
+    if (componentName == null) {
+      if (other.componentName != null) {
+        return false;
+      }
+    } else if (!componentName.equals(other.componentName)) {
+      return false;
+    }
+    if (grantOption == null) {
+      if (other.grantOption != null) {
+        return false;
+      }
+    } else if (!grantOption.equals(other.grantOption)) {
+      return false;
+    }
+
+    List<? extends Authorizable> authorizables = getAuthorizables();
+    List<? extends Authorizable> otherAuthorizables = other.getAuthorizables();
+
+    if (authorizables.size() != otherAuthorizables.size()) {
+      return false;
+    }
+    for (int i = 0; i < authorizables.size(); i++) {
+      String o1 = KV_JOINER.join(authorizables.get(i).getTypeName(),
+          authorizables.get(i).getName());
+      String o2 = KV_JOINER.join(otherAuthorizables.get(i).getTypeName(),
+          otherAuthorizables.get(i).getName());
+      if (!o1.equals(o2)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Return true if this privilege implies request privilege
+   * Otherwise, return false
+   * @param request, other privilege
+   */
+  public boolean implies(MSentryGMPrivilege request) {
+    //component check
+    if (!componentName.equals(request.getComponentName())) {
+      return false;
+    }
+    //service check
+    if (!serviceName.equals(request.getServiceName())) {
+      return false;
+    }
+    // check action implies
+    if (!action.equalsIgnoreCase(AccessConstants.ALL)
+        && !action.equalsIgnoreCase(request.getAction())
+        && !action.equalsIgnoreCase(AccessConstants.ACTION_ALL)) {
+      return false;
+    }
+    //check authorizable list implies
+    Iterator<? extends Authorizable> existIterator = getAuthorizables().iterator();
+    Iterator<? extends Authorizable> requestIterator = request.getAuthorizables().iterator();
+    while (existIterator.hasNext() && requestIterator.hasNext()) {
+      Authorizable existAuth = existIterator.next();
+      Authorizable requestAuth = requestIterator.next();
+      //check authorizable type
+      if (!existAuth.getTypeName().equals(requestAuth.getTypeName())) {
+        return false;
+      }
+      //check authorizable name
+      if (!existAuth.getName().equals(requestAuth.getName())) {
+        /**The persistent authorizable isn't equal the request authorizable
+         * but the following situations are pass check
+         * The name of persistent authorizable is ALL or "*"
+         */
+        if (existAuth.getName().equalsIgnoreCase(AccessConstants.ACTION_ALL)
+            || existAuth.getName().equalsIgnoreCase(AccessConstants.ALL)) {
+          continue;
+        } else {
+          return false;
+        }
+      }
+    }
+
+    if ( !existIterator.hasNext() && !requestIterator.hasNext() ){
+      /**
+       * The persistent privilege has the same authorizables size as the requested privilege
+       * The check is pass
+       */
+      return true;
+
+    } else if (existIterator.hasNext()) {
+      /**
+       * The persistent privilege has much more authorizables than request privilege,so its scope is less
+       * than the requested privilege.
+       * There is a situation that the check is pass, the name of the exceeding authorizables is ALL or "*".
+       * Take the Solr for example,the exist privilege is collection=c1->field=*->action=query
+       * the request privilege is collection=c1->action=query, the check is pass
+       */
+      while (existIterator.hasNext()) {
+        Authorizable existAuthorizable = existIterator.next();
+        if (existAuthorizable.getName().equalsIgnoreCase(AccessConstants.ALL)
+            || existAuthorizable.getName().equalsIgnoreCase(AccessConstants.ACTION_ALL)) {
+          continue;
+        } else {
+          return false;
+        }
+      }
+    } else {
+      /**
+       * The requested privilege has much more authorizables than persistent privilege, so its scope is less
+       * than the persistent privilege
+       * The check is pass
+       */
+      return true;
+    }
+
+    return true;
+  }
+
+  public static String toNULLCol(String col) {
+    return Strings.isNullOrEmpty(col) ? NULL_COL : col;
+  }
+
+  public static boolean notNULL(String s) {
+    return !(Strings.isNullOrEmpty(s) || NULL_COL.equals(s));
+  }
+
+  public static boolean isNULL(String s) {
+    return !notNULL(s);
+  }
+
+  public static <T> void setField(Object obj, String fieldName, T fieldValue) {
+    try {
+      Class<?> clazz = obj.getClass();
+      Field field=clazz.getDeclaredField(fieldName);
+      field.setAccessible(true);
+      field.set(obj, fieldValue);
+    } catch (Exception e) {
+      throw new RuntimeException("setField error: " + e.getMessage(), e);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> T getField(Object obj, String fieldName) {
+    try {
+      Class<?> clazz = obj.getClass();
+      Field field=clazz.getDeclaredField(fieldName);
+      field.setAccessible(true);
+      return (T)field.get(obj);
+    } catch (Exception e) {
+      throw new RuntimeException("getField error: " + e.getMessage(), e);
+    }
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java
new file mode 100644
index 0000000..e0db741
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java
@@ -0,0 +1,112 @@
+/**
+ * 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.service.model;
+
+import java.util.Set;
+
+import javax.jdo.annotations.PersistenceCapable;
+
+/**
+ * Database backed Sentry Group. Any changes to this object
+ * require re-running the maven build so DN an re-enhance.
+ */
+@PersistenceCapable
+public class MSentryGroup {
+
+  /**
+   * Group name is unique
+   */
+  private String groupName;
+  // set of roles granted to this group
+  private Set<MSentryRole> roles;
+  private long createTime;
+
+  public MSentryGroup(String groupName, long createTime, Set<MSentryRole> roles) {
+    this.groupName = MSentryUtil.safeIntern(groupName);
+    this.createTime = createTime;
+    this.roles = roles;
+  }
+
+  public long getCreateTime() {
+    return createTime;
+  }
+
+  public void setCreateTime(long createTime) {
+    this.createTime = createTime;
+  }
+
+  public Set<MSentryRole> getRoles() {
+    return roles;
+  }
+
+  public String getGroupName() {
+    return groupName;
+  }
+
+  public void appendRole(MSentryRole role) {
+    if (roles.add(role)) {
+      role.appendGroup(this);
+    }
+  }
+
+  public void removeRole(MSentryRole role) {
+    if (roles.remove(role)) {
+      role.removeGroup(this);
+    }
+  }
+
+  @Override
+  public String toString() {
+    return "MSentryGroup [groupName=" + groupName + ", roles=[...]"
+        + ", createTime=" + createTime +  "]";
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((groupName == null) ? 0 : groupName.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    MSentryGroup other = (MSentryGroup) obj;
+    if (createTime != other.createTime) {
+      return false;
+    }
+    if (groupName == null) {
+      if (other.groupName != null) {
+        return false;
+      }
+    } else if (!groupName.equals(other.groupName)) {
+      return false;
+    }
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryHmsNotification.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryHmsNotification.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryHmsNotification.java
new file mode 100644
index 0000000..34180e7
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryHmsNotification.java
@@ -0,0 +1,79 @@
+/*
+ * 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.service.model;
+
+/**
+ * Database backend store for HMS Notification ID's. All the notifications that are processed
+ * by sentry are stored.
+ * <p>
+ * <p> HMS notification ID's are stored in separate table for three reasons</p>
+ * <ol>
+ * <li>SENTRY_PATH_CHANGE is not updated for every notification that is received from HMS. There
+ * are cases where HMSFollower doesn't process notifications and skip's them. Depending on
+ * SENTRY_PATH_CHANGE information may not provide the last notification processed.</li>
+ * <li> There could be cases where HMSFollower thread in multiple sentry servers acting as a
+ * leader and process HMS notifications. we need to avoid processing the notifications
+ * multiple times. This can be made sure by always having some number of notification
+ * information always regardless of purging interval.</li>
+ * <li>SENTRY_PATH_CHANGE information stored can typically be removed once namenode plug-in
+ * has processed the update.</li>
+ * </ol>
+ * <p>
+ * As the purpose and usage of notification ID information is different from PATH update info,
+ * it locally makes sense to store notification ID separately.
+ * </p>
+ */
+public class MSentryHmsNotification {
+  private long notificationId;
+
+  public MSentryHmsNotification(long notificationId) {
+    this.notificationId = notificationId;
+  }
+
+  public long getId() {
+    return notificationId;
+  }
+
+  public void setId(long notificationId) {
+    this.notificationId = notificationId;
+  }
+
+  @Override
+  public int hashCode() {
+    return (int) notificationId;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null) {
+      return false;
+    }
+
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+
+    MSentryHmsNotification other = (MSentryHmsNotification) obj;
+
+    return (notificationId == other.notificationId);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPathChange.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPathChange.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPathChange.java
new file mode 100644
index 0000000..bb5ff21
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPathChange.java
@@ -0,0 +1,157 @@
+/**
+ * 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.service.model;
+
+import org.apache.sentry.hdfs.PathsUpdate;
+import org.apache.thrift.TException;
+
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.PrimaryKey;
+
+/**
+ * Database backend store for HMS path delta change. Each record contains
+ * change ID, HMS notification ID, JSON format of a single
+ * &lt Hive Obj, HDFS Path &gt change, and timestamp.
+ * <p>
+ * e.g. for add paths change in JSON format.
+ * <pre>
+ * {@code
+ * {
+ *  "hasFullImage":1,
+ *  "seqNum":1,
+ *  "pathChanges":[
+ *    {
+ *      "authzObj":"db1.tbl12",
+ *      "addPaths":[
+ *        [
+ *          "db1",
+ *          "tbl12",
+ *          "part121"
+ *        ]
+ *      ],
+ *      "delPaths":[]
+ *    }
+ *  ]
+ * }
+ * }
+ * </pre>
+ * <p>
+ * Any changes to this objects require re-running the maven build so DN
+ * can re-enhance.
+ */
+
+@PersistenceCapable
+public class MSentryPathChange implements MSentryChange {
+
+  @PrimaryKey
+  //This value is auto incremented by JDO
+  private long changeID;
+
+  // Path change in JSON format.
+  private String pathChange;
+  private long createTimeMs;
+  private String notificationHash;
+
+  public MSentryPathChange(long changeID, String notificationHash, PathsUpdate pathChange) throws TException {
+    // Each PathsUpdate maps to a MSentryPathChange object.
+    // The PathsUpdate is generated from a HMS notification log,
+    // the notification ID is stored as seqNum and
+    // the notification update is serialized as JSON string.
+    this.changeID = changeID;
+
+    /*
+     * notificationHash is a unique identifier for the HMS notification used to prevent
+     * the same HMS notification message to be processed twice.
+     * The current HMS code may send different notifications messages with the same ID. To
+     * keep this ID unique, we calculate the SHA-1 hash of the full message received.
+     * TODO: This is a temporary fix until HIVE-16886 fixes the issue with duplicated IDs
+     */
+    this.notificationHash = notificationHash;
+
+    this.pathChange = pathChange.JSONSerialize();
+    this.createTimeMs = System.currentTimeMillis();
+  }
+
+  public long getCreateTimeMs() {
+    return createTimeMs;
+  }
+
+  public String getPathChange() {
+    return pathChange;
+  }
+
+  public long getChangeID() {
+    return changeID;
+  }
+
+  public String getNotificationHash() {
+    return notificationHash;
+  }
+
+  @Override
+  public String toString() {
+    return "MSentryChange [changeID=" + changeID + " , notificationHash= "
+        + notificationHash +" , pathChange= " + pathChange +
+        ", createTime=" + createTimeMs +  "]";
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + Long.valueOf(changeID).hashCode();
+    result = prime * result + notificationHash.hashCode();
+    result = prime * result + ((pathChange == null) ? 0 : pathChange.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null) {
+      return false;
+    }
+
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+
+    MSentryPathChange other = (MSentryPathChange) obj;
+    if (changeID != other.changeID) {
+      return false;
+    }
+
+    if (!notificationHash.equals(other.notificationHash)) {
+      return false;
+    }
+
+    if (createTimeMs != other.createTimeMs) {
+      return false;
+    }
+
+    if (pathChange == null) {
+      return other.pathChange == null;
+    }
+
+    return pathChange.equals(other.pathChange);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPermChange.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPermChange.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPermChange.java
new file mode 100644
index 0000000..e29e780
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPermChange.java
@@ -0,0 +1,130 @@
+/**
+ * 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.service.model;
+
+import org.apache.sentry.hdfs.PermissionsUpdate;
+import org.apache.thrift.TException;
+
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.PrimaryKey;
+
+
+/**
+ * Database backend store for Sentry permission delta change. Each record
+ * contains change ID, JSON format of a single Sentry permission change,
+ * and timestamp.
+ * <p>
+ * e.g. for rename privileges change in JSON format.
+ * <pre>
+ * {@code
+ * {
+ *   "hasfullImage":0,
+ *   "seqNum":0,
+ *   "privilegeChanges":{
+ *     "__RENAME_PRIV__":{
+ *       "authzObj":"__RENAME_PRIV__",
+ *       "addPrivileges":{
+ *         "newAuthz":"newAuthz"
+ *       },
+ *       "delPrivileges":{
+ *         "oldAuthz":"oldAuthz"
+ *       }
+ *     }
+ *   },
+ *   "roleChanges":{}
+ * }
+ * </pre>
+ * <p>
+ * Any changes to this objects require re-running the maven build so DN
+ * can re-enhance.
+ */
+@PersistenceCapable
+public class MSentryPermChange implements MSentryChange {
+
+  @PrimaryKey
+  //This value is auto incremented by JDO
+  private long changeID;
+
+  // Permission change in JSON format.
+  private String permChange;
+  private long createTimeMs;
+
+  public MSentryPermChange(long changeID, PermissionsUpdate permChange) throws TException {
+    this.changeID = changeID;
+    this.permChange = permChange.JSONSerialize();
+    this.createTimeMs = System.currentTimeMillis();
+  }
+
+  public long getCreateTimeMs() {
+    return createTimeMs;
+  }
+
+  public String getPermChange() {
+    return permChange;
+  }
+
+  public long getChangeID() {
+    return changeID;
+  }
+
+  @Override
+  public String toString() {
+    return "MSentryPermChange [changeID=" + changeID + ", permChange= " + permChange +
+        ", createTimeMs=" + createTimeMs +  "]";
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + Long.valueOf(changeID).hashCode();
+    result = prime * result + ((permChange == null) ? 0 : permChange.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null) {
+      return false;
+    }
+
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+
+    MSentryPermChange other = (MSentryPermChange) obj;
+    if (changeID != other.changeID) {
+      return false;
+    }
+
+    if (createTimeMs != other.createTimeMs) {
+      return false;
+    }
+
+    if (permChange == null) {
+      return other.permChange == null;
+    }
+
+    return permChange.equals(other.permChange);
+  }
+}


Mime
View raw message