Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.hadoop.hbase.security.access;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.hbase.client.security.SecurityCapability;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.yetus.audience.InterfaceAudience;
/**
* Utility client for doing access control admin operations.
*/
@InterfaceAudience.Public
public class AccessControlClient {
public static final TableName ACL_TABLE_NAME =
TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR, "acl");
/**
* Return true if authorization is supported and enabled
* @param connection The connection to use
* @return true if authorization is supported and enabled, false otherwise
*/
public static boolean isAuthorizationEnabled(Connection connection) throws IOException {
return connection.getAdmin().getSecurityCapabilities()
.contains(SecurityCapability.AUTHORIZATION);
}
/**
* Return true if cell authorization is supported and enabled
* @param connection The connection to use
* @return true if cell authorization is supported and enabled, false otherwise
*/
public static boolean isCellAuthorizationEnabled(Connection connection) throws IOException {
return connection.getAdmin().getSecurityCapabilities()
.contains(SecurityCapability.CELL_AUTHORIZATION);
}
/**
* Grants permission on the specified table for the specified user
* @param connection The Connection instance to use
* @param tableName the table name
* @param userName the user name
* @param family the column family
* @param qual the column qualifier
* @param mergeExistingPermissions If set to false, later granted permissions will override
* previous granted permissions. otherwise, it'll merge with
* previous granted permissions.
* @param actions the actions
*/
private static void grant(Connection connection, final TableName tableName, final String userName,
final byte[] family, final byte[] qual, boolean mergeExistingPermissions,
final Permission.Action... actions) throws Throwable {
connection.getAdmin().grant(new UserPermission(userName, Permission.newBuilder(tableName)
.withFamily(family).withQualifier(qual).withActions(actions).build()),
mergeExistingPermissions);
}
/**
* Grants permission on the specified table for the specified user. If permissions for a specified
* user exists, later granted permissions will override previous granted permissions.
* @param connection The Connection instance to use
* @param tableName the table name
* @param userName the user name
* @param family the column family
* @param qual the column qualifier
* @param actions the actions
*/
public static void grant(Connection connection, final TableName tableName, final String userName,
final byte[] family, final byte[] qual, final Permission.Action... actions) throws Throwable {
grant(connection, tableName, userName, family, qual, true, actions);
}
/**
* Grants permission on the specified namespace for the specified user.
* @param connection The Connection instance to use
* @param namespace the namespace
* @param userName the user name
* @param mergeExistingPermissions If set to false, later granted permissions will override
* previous granted permissions. otherwise, it'll merge with
* previous granted permissions.
* @param actions the actions
*/
private static void grant(Connection connection, final String namespace, final String userName,
boolean mergeExistingPermissions, final Permission.Action... actions) throws Throwable {
connection.getAdmin().grant(
new UserPermission(userName, Permission.newBuilder(namespace).withActions(actions).build()),
mergeExistingPermissions);
}
/**
* Grants permission on the specified namespace for the specified user. If permissions on the
* specified namespace exists, later granted permissions will override previous granted
* permissions.
* @param connection The Connection instance to use
* @param namespace the namespace
* @param userName the user name
* @param actions the actions
*/
public static void grant(Connection connection, final String namespace, final String userName,
final Permission.Action... actions) throws Throwable {
grant(connection, namespace, userName, true, actions);
}
/**
* Grant global permissions for the specified user.
* @param connection The Connection instance to use
* @param userName the user name
* @param mergeExistingPermissions If set to false, later granted permissions will override
* previous granted permissions. otherwise, it'll merge with
* previous granted permissions.
* @param actions the actions
*/
private static void grant(Connection connection, final String userName,
boolean mergeExistingPermissions, final Permission.Action... actions) throws Throwable {
connection.getAdmin().grant(
new UserPermission(userName, Permission.newBuilder().withActions(actions).build()),
mergeExistingPermissions);
}
/**
* Grant global permissions for the specified user. If permissions for the specified user exists,
* later granted permissions will override previous granted permissions.
*/
public static void grant(Connection connection, final String userName,
final Permission.Action... actions) throws Throwable {
grant(connection, userName, true, actions);
}
public static boolean isAccessControllerRunning(Connection connection)
throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
try (Admin admin = connection.getAdmin()) {
return admin.isTableAvailable(ACL_TABLE_NAME);
}
}
/**
* Revokes the permission on the table
* @param connection The Connection instance to use
*/
public static void revoke(Connection connection, final TableName tableName, final String username,
final byte[] family, final byte[] qualifier, final Permission.Action... actions)
throws Throwable {
connection.getAdmin().revoke(new UserPermission(username, Permission.newBuilder(tableName)
.withFamily(family).withQualifier(qualifier).withActions(actions).build()));
}
/**
* Revokes the permission on the namespace for the specified user.
* @param connection The Connection instance to use
*/
public static void revoke(Connection connection, final String namespace, final String userName,
final Permission.Action... actions) throws Throwable {
connection.getAdmin().revoke(
new UserPermission(userName, Permission.newBuilder(namespace).withActions(actions).build()));
}
/**
* Revoke global permissions for the specified user.
* @param connection The Connection instance to use
*/
public static void revoke(Connection connection, final String userName,
final Permission.Action... actions) throws Throwable {
connection.getAdmin()
.revoke(new UserPermission(userName, Permission.newBuilder().withActions(actions).build()));
}
/**
* List all the userPermissions matching the given pattern. If pattern is null, the behavior is
* dependent on whether user has global admin privileges or not. If yes, the global permissions
* along with the list of superusers would be returned. Else, no rows get returned.
* @param connection The Connection instance to use
* @param tableRegex The regular expression string to match against
* @return List of UserPermissions
*/
public static List getUserPermissions(Connection connection, String tableRegex)
throws Throwable {
return getUserPermissions(connection, tableRegex, HConstants.EMPTY_STRING);
}
/**
* List all the userPermissions matching the given table pattern and user name.
* @param connection Connection
* @param tableRegex The regular expression string to match against
* @param userName User name, if empty then all user permissions will be retrieved.
* @return List of UserPermissions
* @throws Throwable on failure
*/
public static List getUserPermissions(Connection connection, String tableRegex,
String userName) throws Throwable {
List permList = new ArrayList<>();
try (Admin admin = connection.getAdmin()) {
if (tableRegex == null || tableRegex.isEmpty()) {
permList = admin.getUserPermissions(
GetUserPermissionsRequest.newBuilder().withUserName(userName).build());
} else if (tableRegex.charAt(0) == '@') { // Namespaces
String namespaceRegex = tableRegex.substring(1);
for (NamespaceDescriptor nsds : admin.listNamespaceDescriptors()) { // Read out all
// namespaces
String namespace = nsds.getName();
if (namespace.matches(namespaceRegex)) { // Match the given namespace regex?
permList.addAll(admin.getUserPermissions(
GetUserPermissionsRequest.newBuilder(namespace).withUserName(userName).build()));
}
}
} else { // Tables
List htds = admin.listTableDescriptors(Pattern.compile(tableRegex), true);
for (TableDescriptor htd : htds) {
permList.addAll(admin.getUserPermissions(GetUserPermissionsRequest
.newBuilder(htd.getTableName()).withUserName(userName).build()));
}
}
}
return permList;
}
/**
* List all the userPermissions matching the given table pattern and column family.
* @param connection Connection
* @param tableRegex The regular expression string to match against. It shouldn't be null, empty
* or a namespace regular expression.
* @param columnFamily Column family
* @return List of UserPermissions
* @throws Throwable on failure
*/
public static List getUserPermissions(Connection connection, String tableRegex,
byte[] columnFamily) throws Throwable {
return getUserPermissions(connection, tableRegex, columnFamily, null, HConstants.EMPTY_STRING);
}
/**
* List all the userPermissions matching the given table pattern, column family and user name.
* @param connection Connection
* @param tableRegex The regular expression string to match against. It shouldn't be null, empty
* or a namespace regular expression.
* @param columnFamily Column family
* @param userName User name, if empty then all user permissions will be retrieved.
* @return List of UserPermissions
* @throws Throwable on failure
*/
public static List getUserPermissions(Connection connection, String tableRegex,
byte[] columnFamily, String userName) throws Throwable {
return getUserPermissions(connection, tableRegex, columnFamily, null, userName);
}
/**
* List all the userPermissions matching the given table pattern, column family and column
* qualifier.
* @param connection Connection
* @param tableRegex The regular expression string to match against. It shouldn't be null,
* empty or a namespace regular expression.
* @param columnFamily Column family
* @param columnQualifier Column qualifier
* @return List of UserPermissions
* @throws Throwable on failure
*/
public static List getUserPermissions(Connection connection, String tableRegex,
byte[] columnFamily, byte[] columnQualifier) throws Throwable {
return getUserPermissions(connection, tableRegex, columnFamily, columnQualifier,
HConstants.EMPTY_STRING);
}
/**
* List all the userPermissions matching the given table pattern, column family and column
* qualifier.
* @param connection Connection
* @param tableRegex The regular expression string to match against. It shouldn't be null,
* empty or a namespace regular expression.
* @param columnFamily Column family
* @param columnQualifier Column qualifier
* @param userName User name, if empty then all user permissions will be retrieved.
* @return List of UserPermissions
* @throws Throwable on failure
*/
public static List getUserPermissions(Connection connection, String tableRegex,
byte[] columnFamily, byte[] columnQualifier, String userName) throws Throwable {
if (tableRegex == null || tableRegex.isEmpty() || tableRegex.charAt(0) == '@') {
throw new IllegalArgumentException("Table name can't be null or empty or a namespace.");
}
List permList = new ArrayList();
try (Admin admin = connection.getAdmin()) {
List htds = admin.listTableDescriptors(Pattern.compile(tableRegex), true);
// Retrieve table permissions
for (TableDescriptor htd : htds) {
permList.addAll(admin.getUserPermissions(
GetUserPermissionsRequest.newBuilder(htd.getTableName()).withFamily(columnFamily)
.withQualifier(columnQualifier).withUserName(userName).build()));
}
}
return permList;
}
/**
* Validates whether specified user has permission to perform actions on the mentioned table,
* column family or column qualifier.
* @param connection Connection
* @param tableName Table name, it shouldn't be null or empty.
* @param columnFamily The column family. Optional argument, can be empty. If empty then
* validation will happen at table level.
* @param columnQualifier The column qualifier. Optional argument, can be empty. If empty then
* validation will happen at table and column family level. columnQualifier
* will not be considered if columnFamily is passed as null or empty.
* @param userName User name, it shouldn't be null or empty.
* @param actions Actions
* @return true if access allowed to the specified user, otherwise false.
* @throws Throwable on failure
*/
public static boolean hasPermission(Connection connection, String tableName, String columnFamily,
String columnQualifier, String userName, Permission.Action... actions) throws Throwable {
return hasPermission(connection, tableName, Bytes.toBytes(columnFamily),
Bytes.toBytes(columnQualifier), userName, actions);
}
/**
* Validates whether specified user has permission to perform actions on the mentioned table,
* column family or column qualifier.
* @param connection Connection
* @param tableName Table name, it shouldn't be null or empty.
* @param columnFamily The column family. Optional argument, can be empty. If empty then
* validation will happen at table level.
* @param columnQualifier The column qualifier. Optional argument, can be empty. If empty then
* validation will happen at table and column family level. columnQualifier
* will not be considered if columnFamily is passed as null or empty.
* @param userName User name, it shouldn't be null or empty.
* @param actions Actions
* @return true if access allowed to the specified user, otherwise false.
* @throws Throwable on failure
*/
public static boolean hasPermission(Connection connection, String tableName, byte[] columnFamily,
byte[] columnQualifier, String userName, Permission.Action... actions) throws Throwable {
if (StringUtils.isEmpty(tableName) || StringUtils.isEmpty(userName)) {
throw new IllegalArgumentException("Table and user name can't be null or empty.");
}
List permissions = new ArrayList<>(1);
permissions.add(Permission.newBuilder(TableName.valueOf(tableName)).withFamily(columnFamily)
.withQualifier(columnQualifier).withActions(actions).build());
return connection.getAdmin().hasUserPermissions(userName, permissions).get(0);
}
}