HBASE-14122 Client API for determining if server side supports cell level security
This commit is contained in:
parent
ba328d26ea
commit
ba4cc6321b
|
@ -37,6 +37,7 @@ import org.apache.hadoop.hbase.TableName;
|
||||||
import org.apache.hadoop.hbase.TableNotFoundException;
|
import org.apache.hadoop.hbase.TableNotFoundException;
|
||||||
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
||||||
|
import org.apache.hadoop.hbase.client.security.SecurityCapability;
|
||||||
import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
|
import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.AdminProtos;
|
import org.apache.hadoop.hbase.protobuf.generated.AdminProtos;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
|
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
|
||||||
|
@ -1408,4 +1409,11 @@ public interface Admin extends Abortable, Closeable {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public int getMasterInfoPort() throws IOException;
|
public int getMasterInfoPort() throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the set of supported security capabilities.
|
||||||
|
* @throws IOException
|
||||||
|
* @throws UnsupportedOperationException
|
||||||
|
*/
|
||||||
|
List<SecurityCapability> getSecurityCapabilities() throws IOException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,4 +300,5 @@ public interface ClusterConnection extends HConnection {
|
||||||
* @return the configured client backoff policy
|
* @return the configured client backoff policy
|
||||||
*/
|
*/
|
||||||
ClientBackoffPolicy getBackoffPolicy();
|
ClientBackoffPolicy getBackoffPolicy();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,8 @@ import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotRe
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanResponse;
|
||||||
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SecurityCapabilitiesRequest;
|
||||||
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SecurityCapabilitiesResponse;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningResponse;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetQuotaRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetQuotaRequest;
|
||||||
|
@ -2030,6 +2032,12 @@ class ConnectionManager {
|
||||||
IsBalancerEnabledRequest request) throws ServiceException {
|
IsBalancerEnabledRequest request) throws ServiceException {
|
||||||
return stub.isBalancerEnabled(controller, request);
|
return stub.isBalancerEnabled(controller, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SecurityCapabilitiesResponse getSecurityCapabilities(RpcController controller,
|
||||||
|
SecurityCapabilitiesRequest request) throws ServiceException {
|
||||||
|
return stub.getSecurityCapabilities(controller, request);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
||||||
import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor;
|
import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor;
|
||||||
import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitorBase;
|
import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitorBase;
|
||||||
|
import org.apache.hadoop.hbase.client.security.SecurityCapability;
|
||||||
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
||||||
import org.apache.hadoop.hbase.exceptions.TimeoutIOException;
|
import org.apache.hadoop.hbase.exceptions.TimeoutIOException;
|
||||||
import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
|
import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
|
||||||
|
@ -135,6 +136,7 @@ import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyTableReques
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
|
||||||
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SecurityCapabilitiesRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ShutdownRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ShutdownRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SnapshotRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SnapshotRequest;
|
||||||
|
@ -4366,4 +4368,23 @@ public class HBaseAdmin implements Admin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SecurityCapability> getSecurityCapabilities() throws IOException {
|
||||||
|
try {
|
||||||
|
return executeCallable(new MasterCallable<List<SecurityCapability>>(getConnection()) {
|
||||||
|
@Override
|
||||||
|
public List<SecurityCapability> call(int callTimeout) throws ServiceException {
|
||||||
|
SecurityCapabilitiesRequest req = SecurityCapabilitiesRequest.newBuilder().build();
|
||||||
|
return ProtobufUtil.toSecurityCapabilityList(
|
||||||
|
master.getSecurityCapabilities(null, req).getCapabilitiesList());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (e instanceof RemoteException) {
|
||||||
|
e = ((RemoteException)e).unwrapRemoteException();
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.hadoop.hbase.client.security;
|
||||||
|
|
||||||
|
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
||||||
|
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Available security capabilities
|
||||||
|
*/
|
||||||
|
@InterfaceAudience.Public
|
||||||
|
@InterfaceStability.Evolving
|
||||||
|
public enum SecurityCapability {
|
||||||
|
// Note to implementors: These must match the numbering of Capability values in MasterProtos
|
||||||
|
SIMPLE_AUTHENTICATION(0),
|
||||||
|
SECURE_AUTHENTICATION(1),
|
||||||
|
AUTHORIZATION(2),
|
||||||
|
CELL_AUTHORIZATION(3),
|
||||||
|
CELL_VISIBILITY(4);
|
||||||
|
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SecurityCapability(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SecurityCapability valueOf(int value) {
|
||||||
|
switch (value) {
|
||||||
|
case 0: return SIMPLE_AUTHENTICATION;
|
||||||
|
case 1: return SECURE_AUTHENTICATION;
|
||||||
|
case 2: return AUTHORIZATION;
|
||||||
|
case 3: return CELL_AUTHORIZATION;
|
||||||
|
case 4: return CELL_VISIBILITY;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown SecurityCapability value " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -65,6 +65,7 @@ import org.apache.hadoop.hbase.client.Put;
|
||||||
import org.apache.hadoop.hbase.client.Result;
|
import org.apache.hadoop.hbase.client.Result;
|
||||||
import org.apache.hadoop.hbase.client.Scan;
|
import org.apache.hadoop.hbase.client.Scan;
|
||||||
import org.apache.hadoop.hbase.client.metrics.ScanMetrics;
|
import org.apache.hadoop.hbase.client.metrics.ScanMetrics;
|
||||||
|
import org.apache.hadoop.hbase.client.security.SecurityCapability;
|
||||||
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
||||||
import org.apache.hadoop.hbase.filter.ByteArrayComparable;
|
import org.apache.hadoop.hbase.filter.ByteArrayComparable;
|
||||||
import org.apache.hadoop.hbase.filter.Filter;
|
import org.apache.hadoop.hbase.filter.Filter;
|
||||||
|
@ -117,6 +118,7 @@ import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionInfo;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier;
|
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
|
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MapReduceProtos;
|
import org.apache.hadoop.hbase.protobuf.generated.MapReduceProtos;
|
||||||
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MasterService;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MasterService;
|
||||||
|
@ -3208,4 +3210,23 @@ public final class ProtobufUtil {
|
||||||
builder.setSrcChecksum(VersionInfo.getSrcChecksum());
|
builder.setSrcChecksum(VersionInfo.getSrcChecksum());
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert SecurityCapabilitiesResponse.Capability to SecurityCapability
|
||||||
|
* @param caps capabilities returned in the SecurityCapabilitiesResponse message
|
||||||
|
* @return the converted list of SecurityCapability elements
|
||||||
|
*/
|
||||||
|
public static List<SecurityCapability> toSecurityCapabilityList(
|
||||||
|
List<MasterProtos.SecurityCapabilitiesResponse.Capability> capabilities) {
|
||||||
|
List<SecurityCapability> scList = new ArrayList<>(capabilities.size());
|
||||||
|
for (MasterProtos.SecurityCapabilitiesResponse.Capability c: capabilities) {
|
||||||
|
try {
|
||||||
|
scList.add(SecurityCapability.valueOf(c.getNumber()));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// Unknown capability, just ignore it. We don't understand the new capability
|
||||||
|
// but don't care since by definition we cannot take advantage of it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.apache.hadoop.hbase.client.Admin;
|
||||||
import org.apache.hadoop.hbase.client.Connection;
|
import org.apache.hadoop.hbase.client.Connection;
|
||||||
import org.apache.hadoop.hbase.client.ConnectionFactory;
|
import org.apache.hadoop.hbase.client.ConnectionFactory;
|
||||||
import org.apache.hadoop.hbase.client.Table;
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
|
import org.apache.hadoop.hbase.client.security.SecurityCapability;
|
||||||
import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
|
import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
|
||||||
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
|
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
|
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
|
||||||
|
@ -50,6 +51,28 @@ public class AccessControlClient {
|
||||||
public static final TableName ACL_TABLE_NAME =
|
public static final TableName ACL_TABLE_NAME =
|
||||||
TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR, "acl");
|
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
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static boolean isCellAuthorizationEnabled(Connection connection) throws IOException {
|
||||||
|
return connection.getAdmin().getSecurityCapabilities()
|
||||||
|
.contains(SecurityCapability.CELL_AUTHORIZATION);
|
||||||
|
}
|
||||||
|
|
||||||
private static BlockingInterface getAccessControlServiceStub(Table ht)
|
private static BlockingInterface getAccessControlServiceStub(Table ht)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
CoprocessorRpcChannel service = ht.coprocessorService(HConstants.EMPTY_START_ROW);
|
CoprocessorRpcChannel service = ht.coprocessorService(HConstants.EMPTY_START_ROW);
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.hadoop.hbase.client.Connection;
|
||||||
import org.apache.hadoop.hbase.client.ConnectionFactory;
|
import org.apache.hadoop.hbase.client.ConnectionFactory;
|
||||||
import org.apache.hadoop.hbase.client.Table;
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
import org.apache.hadoop.hbase.client.coprocessor.Batch;
|
import org.apache.hadoop.hbase.client.coprocessor.Batch;
|
||||||
|
import org.apache.hadoop.hbase.client.security.SecurityCapability;
|
||||||
import org.apache.hadoop.hbase.ipc.BlockingRpcCallback;
|
import org.apache.hadoop.hbase.ipc.BlockingRpcCallback;
|
||||||
import org.apache.hadoop.hbase.ipc.ServerRpcController;
|
import org.apache.hadoop.hbase.ipc.ServerRpcController;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsRequest;
|
||||||
|
@ -55,6 +56,17 @@ import com.google.protobuf.ServiceException;
|
||||||
@InterfaceStability.Evolving
|
@InterfaceStability.Evolving
|
||||||
public class VisibilityClient {
|
public class VisibilityClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if cell visibility features are supported and enabled
|
||||||
|
* @param connection The connection to use
|
||||||
|
* @return true if cell visibility features are supported and enabled, false otherwise
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static boolean isCellVisibilityEnabled(Connection connection) throws IOException {
|
||||||
|
return connection.getAdmin().getSecurityCapabilities()
|
||||||
|
.contains(SecurityCapability.CELL_VISIBILITY);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility method for adding label to the system.
|
* Utility method for adding label to the system.
|
||||||
*
|
*
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -440,6 +440,21 @@ message MajorCompactionTimestampResponse {
|
||||||
required int64 compaction_timestamp = 1;
|
required int64 compaction_timestamp = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message SecurityCapabilitiesRequest {
|
||||||
|
}
|
||||||
|
|
||||||
|
message SecurityCapabilitiesResponse {
|
||||||
|
enum Capability {
|
||||||
|
SIMPLE_AUTHENTICATION = 0;
|
||||||
|
SECURE_AUTHENTICATION = 1;
|
||||||
|
AUTHORIZATION = 2;
|
||||||
|
CELL_AUTHORIZATION = 3;
|
||||||
|
CELL_VISIBILITY = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
repeated Capability capabilities = 1;
|
||||||
|
}
|
||||||
|
|
||||||
service MasterService {
|
service MasterService {
|
||||||
/** Used by the client to get the number of regions that have received the updated schema */
|
/** Used by the client to get the number of regions that have received the updated schema */
|
||||||
rpc GetSchemaAlterStatus(GetSchemaAlterStatusRequest)
|
rpc GetSchemaAlterStatus(GetSchemaAlterStatusRequest)
|
||||||
|
@ -667,4 +682,8 @@ service MasterService {
|
||||||
|
|
||||||
rpc getProcedureResult(GetProcedureResultRequest)
|
rpc getProcedureResult(GetProcedureResultRequest)
|
||||||
returns(GetProcedureResultResponse);
|
returns(GetProcedureResultResponse);
|
||||||
|
|
||||||
|
/** Returns the security capabilities in effect on the cluster */
|
||||||
|
rpc getSecurityCapabilities(SecurityCapabilitiesRequest)
|
||||||
|
returns(SecurityCapabilitiesResponse);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,9 @@ package org.apache.hadoop.hbase.master;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -133,6 +135,9 @@ import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotRe
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanResponse;
|
||||||
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SecurityCapabilitiesRequest;
|
||||||
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SecurityCapabilitiesResponse;
|
||||||
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SecurityCapabilitiesResponse.Capability;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningResponse;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetQuotaRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetQuotaRequest;
|
||||||
|
@ -160,6 +165,9 @@ import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.Repor
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionResponse;
|
||||||
import org.apache.hadoop.hbase.regionserver.RSRpcServices;
|
import org.apache.hadoop.hbase.regionserver.RSRpcServices;
|
||||||
|
import org.apache.hadoop.hbase.security.User;
|
||||||
|
import org.apache.hadoop.hbase.security.access.AccessController;
|
||||||
|
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
||||||
import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
|
import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
|
||||||
import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
|
import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
|
@ -1388,4 +1396,44 @@ public class MasterRpcServices extends RSRpcServices
|
||||||
throw new ServiceException(e);
|
throw new ServiceException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the security capabilities in effect on the cluster
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SecurityCapabilitiesResponse getSecurityCapabilities(RpcController controller,
|
||||||
|
SecurityCapabilitiesRequest request) throws ServiceException {
|
||||||
|
SecurityCapabilitiesResponse.Builder response = SecurityCapabilitiesResponse.newBuilder();
|
||||||
|
try {
|
||||||
|
master.checkInitialized();
|
||||||
|
Set<Capability> capabilities = new HashSet<>();
|
||||||
|
// Authentication
|
||||||
|
if (User.isHBaseSecurityEnabled(master.getConfiguration())) {
|
||||||
|
capabilities.add(Capability.SECURE_AUTHENTICATION);
|
||||||
|
} else {
|
||||||
|
capabilities.add(Capability.SIMPLE_AUTHENTICATION);
|
||||||
|
}
|
||||||
|
// The AccessController can provide AUTHORIZATION and CELL_AUTHORIZATION
|
||||||
|
if (master.cpHost != null &&
|
||||||
|
master.cpHost.findCoprocessor(AccessController.class.getName()) != null) {
|
||||||
|
if (AccessController.isAuthorizationSupported(master.getConfiguration())) {
|
||||||
|
capabilities.add(Capability.AUTHORIZATION);
|
||||||
|
}
|
||||||
|
if (AccessController.isCellAuthorizationSupported(master.getConfiguration())) {
|
||||||
|
capabilities.add(Capability.CELL_AUTHORIZATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The VisibilityController can provide CELL_VISIBILITY
|
||||||
|
if (master.cpHost != null &&
|
||||||
|
master.cpHost.findCoprocessor(VisibilityController.class.getName()) != null) {
|
||||||
|
if (VisibilityController.isCellAuthorizationSupported(master.getConfiguration())) {
|
||||||
|
capabilities.add(Capability.CELL_VISIBILITY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.addAllCapabilities(capabilities);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ServiceException(e);
|
||||||
|
}
|
||||||
|
return response.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,6 +208,15 @@ public class AccessController extends BaseMasterAndRegionObserver
|
||||||
/** if the ACL table is available, only relevant in the master */
|
/** if the ACL table is available, only relevant in the master */
|
||||||
private volatile boolean aclTabAvailable = false;
|
private volatile boolean aclTabAvailable = false;
|
||||||
|
|
||||||
|
public static boolean isAuthorizationSupported(Configuration conf) {
|
||||||
|
return conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCellAuthorizationSupported(Configuration conf) {
|
||||||
|
return isAuthorizationSupported(conf) &&
|
||||||
|
(HFile.getFormatVersion(conf) >= HFile.MIN_FORMAT_VERSION_WITH_TAGS);
|
||||||
|
}
|
||||||
|
|
||||||
public Region getRegion() {
|
public Region getRegion() {
|
||||||
return regionEnv != null ? regionEnv.getRegion() : null;
|
return regionEnv != null ? regionEnv.getRegion() : null;
|
||||||
}
|
}
|
||||||
|
@ -924,7 +933,7 @@ public class AccessController extends BaseMasterAndRegionObserver
|
||||||
CompoundConfiguration conf = new CompoundConfiguration();
|
CompoundConfiguration conf = new CompoundConfiguration();
|
||||||
conf.add(env.getConfiguration());
|
conf.add(env.getConfiguration());
|
||||||
|
|
||||||
authorizationEnabled = conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
|
authorizationEnabled = isAuthorizationSupported(conf);
|
||||||
if (!authorizationEnabled) {
|
if (!authorizationEnabled) {
|
||||||
LOG.warn("The AccessController has been loaded with authorization checks disabled.");
|
LOG.warn("The AccessController has been loaded with authorization checks disabled.");
|
||||||
}
|
}
|
||||||
|
@ -932,7 +941,7 @@ public class AccessController extends BaseMasterAndRegionObserver
|
||||||
shouldCheckExecPermission = conf.getBoolean(AccessControlConstants.EXEC_PERMISSION_CHECKS_KEY,
|
shouldCheckExecPermission = conf.getBoolean(AccessControlConstants.EXEC_PERMISSION_CHECKS_KEY,
|
||||||
AccessControlConstants.DEFAULT_EXEC_PERMISSION_CHECKS);
|
AccessControlConstants.DEFAULT_EXEC_PERMISSION_CHECKS);
|
||||||
|
|
||||||
cellFeaturesEnabled = HFile.getFormatVersion(conf) >= HFile.MIN_FORMAT_VERSION_WITH_TAGS;
|
cellFeaturesEnabled = (HFile.getFormatVersion(conf) >= HFile.MIN_FORMAT_VERSION_WITH_TAGS);
|
||||||
if (!cellFeaturesEnabled) {
|
if (!cellFeaturesEnabled) {
|
||||||
LOG.info("A minimum HFile version of " + HFile.MIN_FORMAT_VERSION_WITH_TAGS
|
LOG.info("A minimum HFile version of " + HFile.MIN_FORMAT_VERSION_WITH_TAGS
|
||||||
+ " is required to persist cell ACLs. Consider setting " + HFile.FORMAT_VERSION_KEY
|
+ " is required to persist cell ACLs. Consider setting " + HFile.FORMAT_VERSION_KEY
|
||||||
|
|
|
@ -148,11 +148,19 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
|
||||||
RESERVED_VIS_TAG_TYPES.add(TagType.STRING_VIS_TAG_TYPE);
|
RESERVED_VIS_TAG_TYPES.add(TagType.STRING_VIS_TAG_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isAuthorizationSupported(Configuration conf) {
|
||||||
|
return conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCellAuthorizationSupported(Configuration conf) {
|
||||||
|
return isAuthorizationSupported(conf);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(CoprocessorEnvironment env) throws IOException {
|
public void start(CoprocessorEnvironment env) throws IOException {
|
||||||
this.conf = env.getConfiguration();
|
this.conf = env.getConfiguration();
|
||||||
|
|
||||||
authorizationEnabled = conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
|
authorizationEnabled = isAuthorizationSupported(conf);
|
||||||
if (!authorizationEnabled) {
|
if (!authorizationEnabled) {
|
||||||
LOG.warn("The VisibilityController has been loaded with authorization checks disabled.");
|
LOG.warn("The VisibilityController has been loaded with authorization checks disabled.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@ import org.apache.hadoop.hbase.client.Result;
|
||||||
import org.apache.hadoop.hbase.client.ResultScanner;
|
import org.apache.hadoop.hbase.client.ResultScanner;
|
||||||
import org.apache.hadoop.hbase.client.Scan;
|
import org.apache.hadoop.hbase.client.Scan;
|
||||||
import org.apache.hadoop.hbase.client.Table;
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
|
import org.apache.hadoop.hbase.client.security.SecurityCapability;
|
||||||
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
|
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
|
||||||
import org.apache.hadoop.hbase.coprocessor.CoprocessorService;
|
import org.apache.hadoop.hbase.coprocessor.CoprocessorService;
|
||||||
import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
|
import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
|
||||||
|
@ -317,6 +318,16 @@ public class TestAccessController extends SecureTestUtil {
|
||||||
TEST_TABLE.getNamespaceAsString()).size());
|
TEST_TABLE.getNamespaceAsString()).size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSecurityCapabilities() throws Exception {
|
||||||
|
List<SecurityCapability> capabilities = TEST_UTIL.getConnection().getAdmin()
|
||||||
|
.getSecurityCapabilities();
|
||||||
|
assertTrue("AUTHORIZATION capability is missing",
|
||||||
|
capabilities.contains(SecurityCapability.AUTHORIZATION));
|
||||||
|
assertTrue("CELL_AUTHORIZATION capability is missing",
|
||||||
|
capabilities.contains(SecurityCapability.CELL_AUTHORIZATION));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTableCreate() throws Exception {
|
public void testTableCreate() throws Exception {
|
||||||
AccessTestAction createTable = new AccessTestAction() {
|
AccessTestAction createTable = new AccessTestAction() {
|
||||||
|
|
|
@ -54,6 +54,7 @@ import org.apache.hadoop.hbase.client.ResultScanner;
|
||||||
import org.apache.hadoop.hbase.client.RowMutations;
|
import org.apache.hadoop.hbase.client.RowMutations;
|
||||||
import org.apache.hadoop.hbase.client.Scan;
|
import org.apache.hadoop.hbase.client.Scan;
|
||||||
import org.apache.hadoop.hbase.client.Table;
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
|
import org.apache.hadoop.hbase.client.security.SecurityCapability;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionActionResult;
|
import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionActionResult;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse;
|
||||||
|
@ -115,6 +116,14 @@ public abstract class TestVisibilityLabels {
|
||||||
killedRS = false;
|
killedRS = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSecurityCapabilities() throws Exception {
|
||||||
|
List<SecurityCapability> capabilities = TEST_UTIL.getConnection().getAdmin()
|
||||||
|
.getSecurityCapabilities();
|
||||||
|
assertTrue("CELL_VISIBILITY capability is missing",
|
||||||
|
capabilities.contains(SecurityCapability.CELL_VISIBILITY));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleVisibilityLabels() throws Exception {
|
public void testSimpleVisibilityLabels() throws Exception {
|
||||||
TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
|
TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
|
||||||
|
|
|
@ -1007,5 +1007,10 @@ module Hbase
|
||||||
@admin.deleteNamespace(namespace_name)
|
@admin.deleteNamespace(namespace_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------------------------
|
||||||
|
# Get security capabilities
|
||||||
|
def get_security_capabilities
|
||||||
|
@admin.getSecurityCapabilities
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -182,10 +182,23 @@ module Hbase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Make sure that security tables are available
|
# Make sure that security features are available
|
||||||
def security_available?()
|
def security_available?()
|
||||||
raise(ArgumentError, "DISABLED: Security features are not available") \
|
caps = []
|
||||||
unless exists?(org.apache.hadoop.hbase.security.access.AccessControlLists::ACL_TABLE_NAME)
|
begin
|
||||||
|
# Try the getSecurityCapabilities API where supported.
|
||||||
|
# We only need to look at AUTHORIZATION, the AccessController doesn't support
|
||||||
|
# CELL_AUTHORIZATION without AUTHORIZATION also available.
|
||||||
|
caps = @admin.getSecurityCapabilities
|
||||||
|
rescue
|
||||||
|
# If we are unable to use getSecurityCapabilities, fall back with a check for
|
||||||
|
# deployment of the ACL table
|
||||||
|
raise(ArgumentError, "DISABLED: Security features are not available") unless \
|
||||||
|
exists?(org.apache.hadoop.hbase.security.access.AccessControlLists::ACL_TABLE_NAME)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
raise(ArgumentError, "DISABLED: Security features are not available") unless \
|
||||||
|
caps.include? org.apache.hadoop.hbase.client.security.SecurityCapability::AUTHORIZATION
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -35,7 +35,7 @@ module Hbase
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_labels(*args)
|
def add_labels(*args)
|
||||||
lables_table_available?
|
visibility_feature_available?
|
||||||
# Normalize args
|
# Normalize args
|
||||||
if args.kind_of?(Array)
|
if args.kind_of?(Array)
|
||||||
labels = [ args ].flatten.compact
|
labels = [ args ].flatten.compact
|
||||||
|
@ -63,7 +63,7 @@ module Hbase
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_auths(user, *args)
|
def set_auths(user, *args)
|
||||||
lables_table_available?
|
visibility_feature_available?
|
||||||
# Normalize args
|
# Normalize args
|
||||||
if args.kind_of?(Array)
|
if args.kind_of?(Array)
|
||||||
auths = [ args ].flatten.compact
|
auths = [ args ].flatten.compact
|
||||||
|
@ -88,7 +88,7 @@ module Hbase
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_auths(user)
|
def get_auths(user)
|
||||||
lables_table_available?
|
visibility_feature_available?
|
||||||
begin
|
begin
|
||||||
response = VisibilityClient.getAuths(@config, user)
|
response = VisibilityClient.getAuths(@config, user)
|
||||||
if response.nil?
|
if response.nil?
|
||||||
|
@ -102,7 +102,7 @@ module Hbase
|
||||||
end
|
end
|
||||||
|
|
||||||
def list_labels(regex = ".*")
|
def list_labels(regex = ".*")
|
||||||
lables_table_available?
|
visibility_feature_available?
|
||||||
begin
|
begin
|
||||||
response = VisibilityClient.listLabels(@config, regex)
|
response = VisibilityClient.listLabels(@config, regex)
|
||||||
if response.nil?
|
if response.nil?
|
||||||
|
@ -116,7 +116,7 @@ module Hbase
|
||||||
end
|
end
|
||||||
|
|
||||||
def clear_auths(user, *args)
|
def clear_auths(user, *args)
|
||||||
lables_table_available?
|
visibility_feature_available?
|
||||||
# Normalize args
|
# Normalize args
|
||||||
if args.kind_of?(Array)
|
if args.kind_of?(Array)
|
||||||
auths = [ args ].flatten.compact
|
auths = [ args ].flatten.compact
|
||||||
|
@ -141,9 +141,20 @@ module Hbase
|
||||||
end
|
end
|
||||||
|
|
||||||
# Make sure that lables table is available
|
# Make sure that lables table is available
|
||||||
def lables_table_available?()
|
def visibility_feature_available?()
|
||||||
raise(ArgumentError, "DISABLED: Visibility labels feature is not available") \
|
caps = []
|
||||||
unless exists?(VisibilityConstants::LABELS_TABLE_NAME)
|
begin
|
||||||
|
# Try the getSecurityCapabilities API where supported.
|
||||||
|
caps = @admin.getSecurityCapabilities
|
||||||
|
rescue
|
||||||
|
# If we are unable to use getSecurityCapabilities, fall back with a check for
|
||||||
|
# deployment of the labels table
|
||||||
|
raise(ArgumentError, "DISABLED: Visibility labels feature is not available") unless \
|
||||||
|
exists?(VisibilityConstants::LABELS_TABLE_NAME)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
raise(ArgumentError, "DISABLED: Visibility labels feature is not available") unless \
|
||||||
|
caps.include? org.apache.hadoop.hbase.client.security.SecurityCapability::CELL_VISIBILITY
|
||||||
end
|
end
|
||||||
|
|
||||||
# Does table exist?
|
# Does table exist?
|
||||||
|
|
|
@ -394,6 +394,7 @@ Shell.load_command_group(
|
||||||
:full_name => 'SECURITY TOOLS',
|
:full_name => 'SECURITY TOOLS',
|
||||||
:comment => "NOTE: Above commands are only applicable if running with the AccessController coprocessor",
|
:comment => "NOTE: Above commands are only applicable if running with the AccessController coprocessor",
|
||||||
:commands => %w[
|
:commands => %w[
|
||||||
|
list_security_capabilities
|
||||||
grant
|
grant
|
||||||
revoke
|
revoke
|
||||||
user_permission
|
user_permission
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
module Shell
|
||||||
|
module Commands
|
||||||
|
class ListSecurityCapabilities < Command
|
||||||
|
def help
|
||||||
|
return <<-EOF
|
||||||
|
List supported security capabilities
|
||||||
|
|
||||||
|
Example:
|
||||||
|
hbase> list_security_capabilities
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
def command()
|
||||||
|
begin
|
||||||
|
list = admin.get_security_capabilities
|
||||||
|
list.each do |s|
|
||||||
|
puts s.getName
|
||||||
|
end
|
||||||
|
return list.map { |s| s.getName() }
|
||||||
|
rescue Exception => e
|
||||||
|
if e.to_s.include? "UnsupportedOperationException"
|
||||||
|
puts "ERROR: Master does not support getSecurityCapabilities"
|
||||||
|
return []
|
||||||
|
end
|
||||||
|
raise e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue