blob: 8c52df542aab09fbb3e36e23150dfb73eef2749b [file] [log] [blame]
/**
* 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.hdfs;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.hadoop.conf.Configuration;
import org.apache.sentry.hdfs.ServiceConstants.ServerConfig;
import org.apache.sentry.hdfs.UpdateForwarder.ExternalImageRetriever;
import org.apache.sentry.hdfs.service.thrift.TPermissionsUpdate;
import org.apache.sentry.hdfs.service.thrift.TPrivilegeChanges;
import org.apache.sentry.hdfs.service.thrift.TRoleChanges;
import org.apache.sentry.provider.db.SentryPolicyStorePlugin;
import org.apache.sentry.provider.db.service.persistent.SentryStore;
import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleAddGroupsRequest;
import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleDeleteGroupsRequest;
import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleGrantPrivilegeRequest;
import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleRevokePrivilegeRequest;
import org.apache.sentry.provider.db.service.thrift.TDropPrivilegesRequest;
import org.apache.sentry.provider.db.service.thrift.TDropSentryRoleRequest;
import org.apache.sentry.provider.db.service.thrift.TRenamePrivilegesRequest;
import org.apache.sentry.provider.db.service.thrift.TSentryAuthorizable;
import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;
public class SentryPlugin implements SentryPolicyStorePlugin {
private static final Logger LOGGER = LoggerFactory.getLogger(SentryPlugin.class);
public static String NULL_COL = "__NULL__";
public static volatile SentryPlugin instance;
static class PermImageRetriever implements ExternalImageRetriever<PermissionsUpdate> {
private final SentryStore sentryStore;
public PermImageRetriever(SentryStore sentryStore) {
this.sentryStore = sentryStore;
}
@Override
public PermissionsUpdate retrieveFullImage(long currSeqNum) {
Map<String, HashMap<String, String>> privilegeImage = sentryStore.retrieveFullPrivilegeImage();
Map<String, LinkedList<String>> roleImage = sentryStore.retrieveFullRoleImage();
TPermissionsUpdate tPermUpdate = new TPermissionsUpdate(true, currSeqNum,
new HashMap<String, TPrivilegeChanges>(),
new HashMap<String, TRoleChanges>());
for (Map.Entry<String, HashMap<String, String>> privEnt : privilegeImage.entrySet()) {
String authzObj = privEnt.getKey();
HashMap<String,String> privs = privEnt.getValue();
tPermUpdate.putToPrivilegeChanges(authzObj, new TPrivilegeChanges(
authzObj, privs, new HashMap<String, String>()));
}
for (Map.Entry<String, LinkedList<String>> privEnt : roleImage.entrySet()) {
String role = privEnt.getKey();
LinkedList<String> groups = privEnt.getValue();
tPermUpdate.putToRoleChanges(role, new TRoleChanges(role, groups, new LinkedList<String>()));
}
PermissionsUpdate permissionsUpdate = new PermissionsUpdate(tPermUpdate);
permissionsUpdate.setSeqNum(currSeqNum);
return permissionsUpdate;
}
}
private UpdateForwarder<PathsUpdate> pathsUpdater;
private UpdateForwarder<PermissionsUpdate> permsUpdater;
private final AtomicLong permSeqNum = new AtomicLong(5);
private PermImageRetriever permImageRetriever;
long getLastSeenHMSPathSeqNum() {
return pathsUpdater.getLastSeen();
}
@Override
public void initialize(Configuration conf, SentryStore sentryStore) throws SentryPluginException {
final String[] pathPrefixes = conf
.getStrings(ServerConfig.SENTRY_HDFS_INTEGRATION_PATH_PREFIXES,
ServerConfig.SENTRY_HDFS_INTEGRATION_PATH_PREFIXES_DEFAULT);
final int initUpdateRetryDelayMs =
conf.getInt(ServerConfig.SENTRY_HDFS_INIT_UPDATE_RETRY_DELAY_MS,
ServerConfig.SENTRY_HDFS_INIT_UPDATE_RETRY_DELAY_DEFAULT);
pathsUpdater = new UpdateForwarder<PathsUpdate>(new UpdateableAuthzPaths(
pathPrefixes), null, 100, initUpdateRetryDelayMs);
permImageRetriever = new PermImageRetriever(sentryStore);
permsUpdater = new UpdateForwarder<PermissionsUpdate>(
new UpdateablePermissions(permImageRetriever), permImageRetriever,
100, initUpdateRetryDelayMs);
LOGGER.info("Sentry HDFS plugin initialized !!");
instance = this;
}
public List<PathsUpdate> getAllPathsUpdatesFrom(long pathSeqNum) {
return pathsUpdater.getAllUpdatesFrom(pathSeqNum);
}
public List<PermissionsUpdate> getAllPermsUpdatesFrom(long permSeqNum) {
return permsUpdater.getAllUpdatesFrom(permSeqNum);
}
public void handlePathUpdateNotification(PathsUpdate update) {
pathsUpdater.handleUpdateNotification(update);
LOGGER.debug("Recieved Authz Path update [" + update.getSeqNum() + "]..");
}
@Override
public void onAlterSentryRoleAddGroups(
TAlterSentryRoleAddGroupsRequest request) throws SentryPluginException {
PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
TRoleChanges rUpdate = update.addRoleUpdate(request.getRoleName());
for (TSentryGroup group : request.getGroups()) {
rUpdate.addToAddGroups(group.getGroupName());
}
permsUpdater.handleUpdateNotification(update);
LOGGER.debug("Authz Perm preUpdate [" + update.getSeqNum() + ", " + request.getRoleName() + "]..");
}
@Override
public void onAlterSentryRoleDeleteGroups(
TAlterSentryRoleDeleteGroupsRequest request)
throws SentryPluginException {
PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
TRoleChanges rUpdate = update.addRoleUpdate(request.getRoleName());
for (TSentryGroup group : request.getGroups()) {
rUpdate.addToDelGroups(group.getGroupName());
}
permsUpdater.handleUpdateNotification(update);
LOGGER.debug("Authz Perm preUpdate [" + update.getSeqNum() + ", " + request.getRoleName() + "]..");
}
@Override
public void onAlterSentryRoleGrantPrivilege(
TAlterSentryRoleGrantPrivilegeRequest request)
throws SentryPluginException {
if (request.isSetPrivileges()) {
String roleName = request.getRoleName();
for (TSentryPrivilege privilege : request.getPrivileges()) {
onAlterSentryRoleGrantPrivilegeCore(roleName, privilege);
}
}
}
private void onAlterSentryRoleGrantPrivilegeCore(String roleName, TSentryPrivilege privilege)
throws SentryPluginException {
String authzObj = getAuthzObj(privilege);
if (authzObj != null) {
PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
update.addPrivilegeUpdate(authzObj).putToAddPrivileges(
roleName, privilege.getAction().toUpperCase());
permsUpdater.handleUpdateNotification(update);
LOGGER.debug("Authz Perm preUpdate [" + update.getSeqNum() + "]..");
}
}
@Override
public void onRenameSentryPrivilege(TRenamePrivilegesRequest request)
throws SentryPluginException {
String oldAuthz = getAuthzObj(request.getOldAuthorizable());
String newAuthz = getAuthzObj(request.getNewAuthorizable());
PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
TPrivilegeChanges privUpdate = update.addPrivilegeUpdate(PermissionsUpdate.RENAME_PRIVS);
privUpdate.putToAddPrivileges(newAuthz, newAuthz);
privUpdate.putToDelPrivileges(oldAuthz, oldAuthz);
permsUpdater.handleUpdateNotification(update);
LOGGER.debug("Authz Perm preUpdate [" + update.getSeqNum() + ", " + newAuthz + ", " + oldAuthz + "]..");
}
@Override
public void onAlterSentryRoleRevokePrivilege(
TAlterSentryRoleRevokePrivilegeRequest request)
throws SentryPluginException {
if (request.isSetPrivileges()) {
String roleName = request.getRoleName();
for (TSentryPrivilege privilege : request.getPrivileges()) {
onAlterSentryRoleRevokePrivilegeCore(roleName, privilege);
}
}
}
private void onAlterSentryRoleRevokePrivilegeCore(String roleName, TSentryPrivilege privilege)
throws SentryPluginException {
String authzObj = getAuthzObj(privilege);
if (authzObj != null) {
PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
update.addPrivilegeUpdate(authzObj).putToDelPrivileges(
roleName, privilege.getAction().toUpperCase());
permsUpdater.handleUpdateNotification(update);
LOGGER.debug("Authz Perm preUpdate [" + update.getSeqNum() + ", " + authzObj + "]..");
}
}
@Override
public void onDropSentryRole(TDropSentryRoleRequest request)
throws SentryPluginException {
PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
update.addPrivilegeUpdate(PermissionsUpdate.ALL_AUTHZ_OBJ).putToDelPrivileges(
request.getRoleName(), PermissionsUpdate.ALL_AUTHZ_OBJ);
update.addRoleUpdate(request.getRoleName()).addToDelGroups(PermissionsUpdate.ALL_GROUPS);
permsUpdater.handleUpdateNotification(update);
LOGGER.debug("Authz Perm preUpdate [" + update.getSeqNum() + ", " + request.getRoleName() + "]..");
}
@Override
public void onDropSentryPrivilege(TDropPrivilegesRequest request)
throws SentryPluginException {
PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
String authzObj = getAuthzObj(request.getAuthorizable());
update.addPrivilegeUpdate(authzObj).putToDelPrivileges(
PermissionsUpdate.ALL_ROLES, PermissionsUpdate.ALL_ROLES);
permsUpdater.handleUpdateNotification(update);
LOGGER.debug("Authz Perm preUpdate [" + update.getSeqNum() + ", " + authzObj + "]..");
}
private String getAuthzObj(TSentryPrivilege privilege) {
String authzObj = null;
if (!isNULL(privilege.getDbName())) {
String dbName = privilege.getDbName();
String tblName = privilege.getTableName();
if (isNULL(tblName)) {
authzObj = dbName;
} else {
authzObj = dbName + "." + tblName;
}
}
return authzObj;
}
private String getAuthzObj(TSentryAuthorizable authzble) {
String authzObj = null;
if (!isNULL(authzble.getDb())) {
String dbName = authzble.getDb();
String tblName = authzble.getTable();
if (isNULL(tblName)) {
authzObj = dbName;
} else {
authzObj = dbName + "." + tblName;
}
}
return authzObj;
}
public static String toNULLCol(String s) {
return Strings.isNullOrEmpty(s) ? NULL_COL : s;
}
public static String fromNULLCol(String s) {
return isNULL(s) ? "" : s;
}
public static boolean isNULL(String s) {
return Strings.isNullOrEmpty(s) || s.equals(NULL_COL);
}
}