You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by sp...@apache.org on 2018/05/31 03:32:18 UTC
[40/86] sentry git commit: Revert "SENTRY-2208: Refactor out Sentry
service into own module from sentry-provider-db (Anthony Young-Garner,
reviewed by Sergio Pena, Steve Moist, Na Li)"
http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/appender/RollingFileWithoutDeleteAppender.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/appender/RollingFileWithoutDeleteAppender.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/appender/RollingFileWithoutDeleteAppender.java
new file mode 100644
index 0000000..fd133f3
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/appender/RollingFileWithoutDeleteAppender.java
@@ -0,0 +1,175 @@
+/**
+ * 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.appender;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.Writer;
+
+import org.apache.log4j.FileAppender;
+import org.apache.log4j.Layout;
+import org.apache.log4j.helpers.CountingQuietWriter;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.helpers.OptionConverter;
+import org.apache.log4j.spi.LoggingEvent;
+
+public class RollingFileWithoutDeleteAppender extends FileAppender {
+ /**
+ * The default maximum file size is 10MB.
+ */
+ protected long maxFileSize = 10 * 1024 * 1024;
+
+ private long nextRollover = 0;
+
+ /**
+ * The default constructor simply calls its {@link FileAppender#FileAppender
+ * parents constructor}.
+ */
+ public RollingFileWithoutDeleteAppender() {
+ super();
+ }
+
+ /**
+ * Instantiate a RollingFileAppender and open the file designated by
+ * <code>filename</code>. The opened filename will become the ouput
+ * destination for this appender.
+ * <p>
+ * If the <code>append</code> parameter is true, the file will be appended to.
+ * Otherwise, the file desginated by <code>filename</code> will be truncated
+ * before being opened.
+ */
+ public RollingFileWithoutDeleteAppender(Layout layout, String filename,
+ boolean append) throws IOException {
+ super(layout, getLogFileName(filename), append);
+ }
+
+ /**
+ * Instantiate a FileAppender and open the file designated by
+ * <code>filename</code>. The opened filename will become the output
+ * destination for this appender.
+ * <p>
+ * The file will be appended to.
+ */
+ public RollingFileWithoutDeleteAppender(Layout layout, String filename)
+ throws IOException {
+ super(layout, getLogFileName(filename));
+ }
+
+ /**
+ * Get the maximum size that the output file is allowed to reach before being
+ * rolled over to backup files.
+ */
+ public long getMaximumFileSize() {
+ return maxFileSize;
+ }
+
+ /**
+ * Implements the usual roll over behaviour.
+ * <p>
+ * <code>File</code> is renamed <code>File.yyyyMMddHHmmss</code> and closed. A
+ * new <code>File</code> is created to receive further log output.
+ */
+ // synchronization not necessary since doAppend is alreasy synched
+ public void rollOver() {
+ if (qw != null) {
+ long size = ((CountingQuietWriter) qw).getCount();
+ LogLog.debug("rolling over count=" + size);
+ // if operation fails, do not roll again until
+ // maxFileSize more bytes are written
+ nextRollover = size + maxFileSize;
+ }
+
+ this.closeFile(); // keep windows happy.
+
+ String newFileName = getLogFileName(fileName);
+ try {
+ // This will also close the file. This is OK since multiple
+ // close operations are safe.
+ this.setFile(newFileName, false, bufferedIO, bufferSize);
+ nextRollover = 0;
+ } catch (IOException e) {
+ if (e instanceof InterruptedIOException) {
+ Thread.currentThread().interrupt();
+ }
+ LogLog.error("setFile(" + newFileName + ", false) call failed: " + e.getMessage(), e);
+ }
+ }
+
+ public synchronized void setFile(String fileName, boolean append,
+ boolean bufferedIO, int bufferSize) throws IOException {
+ super.setFile(fileName, append, this.bufferedIO, this.bufferSize);
+ if (append) {
+ File f = new File(fileName);
+ ((CountingQuietWriter) qw).setCount(f.length());
+ }
+ }
+
+ /**
+ * Set the maximum size that the output file is allowed to reach before being
+ * rolled over to backup files.
+ * <p>
+ * This method is equivalent to {@link #setMaxFileSize} except that it is
+ * required for differentiating the setter taking a <code>long</code> argument
+ * from the setter taking a <code>String</code> argument by the JavaBeans
+ * {@link java.beans.Introspector Introspector}.
+ *
+ * @see #setMaxFileSize(String)
+ */
+ public void setMaximumFileSize(long maxFileSize) {
+ this.maxFileSize = maxFileSize;
+ }
+
+ /**
+ * Set the maximum size that the output file is allowed to reach before being
+ * rolled over to backup files.
+ * <p>
+ * In configuration files, the <b>MaxFileSize</b> option takes an long integer
+ * in the range 0 - 2^63. You can specify the value with the suffixes "KB",
+ * "MB" or "GB" so that the integer is interpreted being expressed
+ * respectively in kilobytes, megabytes or gigabytes. For example, the value
+ * "10KB" will be interpreted as 10240.
+ */
+ public void setMaxFileSize(String value) {
+ maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1);
+ }
+
+ protected void setQWForFiles(Writer writer) {
+ this.qw = new CountingQuietWriter(writer, errorHandler);
+ }
+
+ /**
+ * This method differentiates RollingFileAppender from its super class.
+ */
+ protected void subAppend(LoggingEvent event) {
+ super.subAppend(event);
+
+ if (fileName != null && qw != null) {
+ long size = ((CountingQuietWriter) qw).getCount();
+ if (size >= maxFileSize && size >= nextRollover) {
+ rollOver();
+ }
+ }
+ }
+
+ // Mangled file name. Append the current timestamp
+ private static String getLogFileName(String oldFileName) {
+ return oldFileName + "." + Long.toString(System.currentTimeMillis());
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/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
new file mode 100644
index 0000000..a5fe4ec
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/AuditMetadataLogEntity.java
@@ -0,0 +1,155 @@
+/**
+ * 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 org.codehaus.jackson.JsonFactory;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.MappingJsonFactory;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.node.ContainerNode;
+
+abstract public class AuditMetadataLogEntity implements JsonLogEntity {
+
+ 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 objectType;
+ private 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;
+ this.ipAddress = ipAddress;
+ this.operation = operation;
+ this.eventTime = eventTime;
+ this.operationText = operationText;
+ this.allowed = allowed;
+ this.objectType = objectType;
+ this.component = component;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public void setServiceName(String serviceName) {
+ this.serviceName = serviceName;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getImpersonator() {
+ return impersonator;
+ }
+
+ public void setImpersonator(String impersonator) {
+ this.impersonator = impersonator;
+ }
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ public String getOperation() {
+ return operation;
+ }
+
+ public void setOperation(String operation) {
+ this.operation = operation;
+ }
+
+ public String getEventTime() {
+ return eventTime;
+ }
+
+ public void setEventTime(String eventTime) {
+ this.eventTime = eventTime;
+ }
+
+ public String getOperationText() {
+ return operationText;
+ }
+
+ public void setOperationText(String operationText) {
+ this.operationText = operationText;
+ }
+
+ public String getAllowed() {
+ return allowed;
+ }
+
+ public void setAllowed(String allowed) {
+ this.allowed = allowed;
+ }
+
+ public String getObjectType() {
+ return objectType;
+ }
+
+ public void setObjectType(String objectType) {
+ this.objectType = objectType;
+ }
+
+ public String getComponent() {
+ return component;
+ }
+
+ public void setComponent(String component) {
+ this.component = component;
+ }
+
+ /**
+ * For use in tests
+ *
+ * @param json
+ * incoming JSON to parse
+ * @return a node tree
+ * @throws IOException
+ * on any parsing problems
+ */
+ public static ContainerNode parse(String json) throws IOException {
+ ObjectMapper mapper = new ObjectMapper(factory);
+ JsonNode jsonNode = mapper.readTree(json);
+ if (!(jsonNode instanceof ContainerNode)) {
+ throw new IOException("Wrong JSON data: " + json);
+ }
+ return (ContainerNode) jsonNode;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/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..4949ac7
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/entity/DBAuditMetadataLogEntity.java
@@ -0,0 +1,124 @@
+/**
+ * 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, 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());
+ 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, getObjectType());
+ 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();
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/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..6911772
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/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/9351d19d/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
new file mode 100644
index 0000000..913f125
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/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/9351d19d/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
new file mode 100644
index 0000000..61becce
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/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/9351d19d/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
new file mode 100644
index 0000000..6479a60
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/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/9351d19d/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
new file mode 100644
index 0000000..6e91f8b
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/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/9351d19d/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsMapping.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsMapping.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsMapping.java
new file mode 100644
index 0000000..c51f25a
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/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/9351d19d/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsSnapshotId.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsSnapshotId.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MAuthzPathsSnapshotId.java
new file mode 100644
index 0000000..d683c2c
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/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/9351d19d/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MPath.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MPath.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MPath.java
new file mode 100644
index 0000000..b0eaff2
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/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/9351d19d/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryChange.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryChange.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryChange.java
new file mode 100644
index 0000000..9b022a1
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/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/9351d19d/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java
new file mode 100644
index 0000000..24ed204
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/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/9351d19d/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java
new file mode 100644
index 0000000..e0db741
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/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;
+ }
+}