Skip to content

Commit

Permalink
Support ranger plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
zzzzming95 committed Sep 28, 2023
1 parent 774f670 commit 66a9606
Show file tree
Hide file tree
Showing 12 changed files with 714 additions and 1 deletion.
21 changes: 21 additions & 0 deletions waggle-dance-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,27 @@
</exclusions>
</dependency>

<!-- Ranger -->
<dependency>
<groupId>org.apache.ranger</groupId>
<artifactId>ranger-hive-plugin</artifactId>
<version>1.2.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.hive</groupId>
<artifactId>hive-common</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- Hadoop -->
<dependency>
<groupId>org.apache.hadoop</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ private void startWaggleDance(
HadoopThriftAuthBridge.Server saslServer = null;

if (useSASL) {
UserGroupInformation.reset();
UserGroupInformation.setConfiguration(hiveConf);
saslServer = SaslHelper.createSaslServer(hiveConf);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/**
* Copyright (C) 2016-2023 Expedia, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hotels.bdp.waggledance.server;

import java.lang.reflect.*;
import java.util.Set;

import org.apache.hadoop.hive.metastore.IHMSHandler;
import org.apache.hadoop.hive.metastore.api.*;
import org.apache.hadoop.security.UserGroupInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Sets;

import com.hotels.bdp.waggledance.server.security.ranger.RangerAccessControlHandler;

public class RangerWrappingHMSHandler implements InvocationHandler {
private final static Logger LOG = LoggerFactory.getLogger(RangerWrappingHMSHandler.class);

private final IHMSHandler baseHandler;
private final RangerAccessControlHandler rangerAccessControlHandler;
private String user;
private Set<String> groups;

public static IHMSHandler newProxyInstance(IHMSHandler baseHandler,
RangerAccessControlHandler rangerAccessControlHandler) {
return (IHMSHandler) Proxy.newProxyInstance(RangerWrappingHMSHandler.class.getClassLoader(),
new Class[]{IHMSHandler.class}, new RangerWrappingHMSHandler(baseHandler, rangerAccessControlHandler));
}

public RangerWrappingHMSHandler(IHMSHandler baseHandler, RangerAccessControlHandler rangerAccessControlHandler) {
this.baseHandler = baseHandler;
this.rangerAccessControlHandler = rangerAccessControlHandler;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (TokenWrappingHMSHandler.getToken().isEmpty())
return method.invoke(baseHandler, args);

if (user == null) {
String userName = UserGroupInformation.getCurrentUser().getShortUserName();
UserGroupInformation ugi = UserGroupInformation.createRemoteUser(userName);
user = userName;
groups = Sets.newHashSet(ugi.getGroupNames());
}

switch (method.getName()) {
// SELECT permissions
case "get_table":
case "get_partition":
case "get_partition_with_auth":
case "get_partition_by_name":
case "get_partitions":
case "get_partitions_with_auth":
case "get_partitions_pspec":
case "get_partition_names":
case "get_partitions_ps":
case "get_partitions_ps_with_auth":
case "get_partition_names_ps":
case "get_partitions_by_filter":
case "get_part_specs_by_filter":
case "get_partitions_by_names":
case "get_table_column_statistics":
case "get_partition_column_statistics":
case "get_fields_with_environment_context":
case "get_num_partitions_by_filter":
this.rangerAccessControlHandler.hasSelectPermission(
(String) args[0], (String) args[1], user, groups);
break;

// DROP permissions
case "drop_table":
case "drop_table_with_environment_context":
this.rangerAccessControlHandler.hasDropPermission(
(String) args[0], (String) args[1], user, groups);
break;

// ALTER permissions
case "alter_table":
case "alter_table_with_environment_context":
case "drop_partition":
case "drop_partition_with_environment_context":
case "drop_partition_by_name":
case "drop_partition_by_name_with_environment_context":
case "alter_partition":
case "alter_partitions":
case "alter_partition_with_environment_context":
case "rename_partition":
case "delete_partition_column_statistics":
case "delete_table_column_statistics":
case "alter_partitions_with_environment_context":
case "alter_table_with_cascade":
case "append_partition":
case "append_partition_with_environment_context":
this.rangerAccessControlHandler.hasAlterPermission(
(String) args[0], (String) args[1], user, groups);
break;

// CREATE permissions
case "create_table":
case "create_table_with_environment_context":
case "create_table_with_constraints":
Table tbl = (Table) args[0];
this.rangerAccessControlHandler.hasCreatePermission(
tbl.getDbName(), tbl.getTableName(), user, groups);
break;

// other case
case "get_partitions_by_expr":
PartitionsByExprRequest partExprReq = (PartitionsByExprRequest) args[0];
this.rangerAccessControlHandler.hasSelectPermission(
partExprReq.getDbName(), partExprReq.getTblName(), user, groups);
break;
case "get_table_statistics_req":
TableStatsRequest tableStatsRequest = (TableStatsRequest) args[0];
this.rangerAccessControlHandler.hasSelectPermission(
tableStatsRequest.getDbName(), tableStatsRequest.getTblName(), user, groups);
break;
case "get_partitions_statistics_req":
case "get_aggr_stats_for":
PartitionsStatsRequest partitionsStatsRequest = (PartitionsStatsRequest) args[0];
this.rangerAccessControlHandler.hasSelectPermission(
partitionsStatsRequest.getDbName(), partitionsStatsRequest.getTblName(), user, groups);
break;
case "get_table_req":
GetTableRequest getTableRequest = (GetTableRequest) args[0];
this.rangerAccessControlHandler.hasSelectPermission(
getTableRequest.getDbName(), getTableRequest.getTblName(), user, groups);
break;
case "get_partition_values":
PartitionValuesRequest partitionValuesRequest = (PartitionValuesRequest) args[0];
this.rangerAccessControlHandler.hasSelectPermission(
partitionValuesRequest.getDbName(), partitionValuesRequest.getTblName(), user, groups);
break;
case "add_partition":
Partition partition = (Partition) args[0];
this.rangerAccessControlHandler.hasAlterPermission(
partition.getDbName(), partition.getTableName(), user, groups);
break;
case "add_partitions_req":
AddPartitionsRequest addPartitionsRequest = (AddPartitionsRequest) args[0];
this.rangerAccessControlHandler.hasAlterPermission(
addPartitionsRequest.getDbName(), addPartitionsRequest.getTblName(), user, groups);
break;
case "drop_partitions_req":
DropPartitionsRequest dropPartitionsRequest = (DropPartitionsRequest) args[0];
this.rangerAccessControlHandler.hasAlterPermission(
dropPartitionsRequest.getDbName(), dropPartitionsRequest.getTblName(), user, groups);
break;
case "update_table_column_statistics":
case "update_partition_column_statistics":
ColumnStatistics columnStatistics = (ColumnStatistics) args[0];
this.rangerAccessControlHandler.hasAlterPermission(
columnStatistics.getStatsDesc().getDbName(),
columnStatistics.getStatsDesc().getTableName(), user, groups);
break;
// special case, pass it
case "add_partitions":
case "add_partitions_pspec":
case "drop_constraint":
case "partition_name_has_valid_characters":
case "set_aggr_stats_for":

default:
break;
}
return method.invoke(baseHandler, args);
} catch (InvocationTargetException e) {
throw e.getCause();
} catch (UndeclaredThrowableException e) {
// Need to unwrap this, so callers get the correct exception thrown by the handler.
throw e.getCause();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.hotels.bdp.waggledance.server.security.ranger.RangerAccessControlFactory;

@Component
class TSetIpAddressProcessorFactory extends TProcessorFactory {

Expand Down Expand Up @@ -61,7 +63,11 @@ public TProcessor getProcessor(TTransport transport) {

boolean useSASL = hiveConf.getBoolVar(HiveConf.ConfVars.METASTORE_USE_THRIFT_SASL);
if (useSASL) {
IHMSHandler tokenHandler = TokenWrappingHMSHandler.newProxyInstance(baseHandler, useSASL);

IHMSHandler rangerHandler = RangerWrappingHMSHandler.newProxyInstance(baseHandler,
RangerAccessControlFactory.getInstance(hiveConf));
IHMSHandler tokenHandler = TokenWrappingHMSHandler.newProxyInstance(rangerHandler, useSASL);

IHMSHandler handler = newRetryingHMSHandler(ExceptionWrappingHMSHandler.newProxyInstance(tokenHandler), hiveConf,
false);
return new TSetIpAddressProcessor<>(handler);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Copyright (C) 2016-2023 Expedia, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hotels.bdp.waggledance.server.security.ranger;

import java.util.Date;
import java.util.Set;

import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
import org.apache.ranger.plugin.policyengine.RangerAccessResource;

public class AccessRequest extends RangerAccessRequestImpl {
private AccessType accessType;
private RangerAccessResource resource;

public AccessRequest(RangerAccessResource resource, AccessType accessType, String user, Set<String> groups) {
this();
this.resource = resource;
this.accessType = accessType;
this.setResource(resource);
this.setAccessType(accessType.name().toLowerCase());
this.setAction(accessType.toString());
this.setUser(user);
this.setUserGroups(groups);
this.setAccessTime(new Date());
}

private AccessRequest() {
super();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Copyright (C) 2016-2023 Expedia, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hotels.bdp.waggledance.server.security.ranger;

public enum AccessType {
NONE, CREATE, ALTER, DROP, INDEX, LOCK, SELECT, UPDATE, INSPECT, USE, ALL, ADMIN

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright (C) 2016-2023 Expedia, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hotels.bdp.waggledance.server.security.ranger;

import java.util.Set;

public class DefaultRangerAccessControlHandler implements RangerAccessControlHandler {

@Override
public boolean hasUpdatePermission(String databaseName, String tableName, String user, Set<String> groups) {
return true;
}

@Override
public boolean hasCreatePermission(String databaseName, String tableName, String user, Set<String> groups) {
return true;
}

@Override
public boolean hasSelectPermission(String databaseName, String tableName, String user, Set<String> groups) {
return true;
}

@Override
public boolean hasDropPermission(String databaseName, String tableName, String user, Set<String> groups) {
return true;
}

@Override
public boolean hasAlterPermission(String databaseName, String tableName, String user, Set<String> groups) {
return true;
}

}
Loading

0 comments on commit 66a9606

Please sign in to comment.