HBASE-24443 Refactor TestCustomSaslAuthenticationProvider (#1790)
Signed-off-by: Guanghao Zhang <zghao@apache.org>
This commit is contained in:
parent
79d56499ca
commit
f06248ef84
|
@ -30,7 +30,6 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -52,7 +51,6 @@ import org.apache.hadoop.conf.Configuration;
|
|||
import org.apache.hadoop.fs.Path;
|
||||
import org.apache.hadoop.hbase.Cell;
|
||||
import org.apache.hadoop.hbase.CellUtil;
|
||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||
import org.apache.hadoop.hbase.HConstants;
|
||||
import org.apache.hadoop.hbase.LocalHBaseCluster;
|
||||
|
@ -72,10 +70,8 @@ import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
|
|||
import org.apache.hadoop.hbase.exceptions.MasterRegistryFetchException;
|
||||
import org.apache.hadoop.hbase.ipc.BlockingRpcClient;
|
||||
import org.apache.hadoop.hbase.ipc.NettyRpcClient;
|
||||
import org.apache.hadoop.hbase.ipc.NettyRpcServer;
|
||||
import org.apache.hadoop.hbase.ipc.RpcClientFactory;
|
||||
import org.apache.hadoop.hbase.ipc.RpcServerFactory;
|
||||
import org.apache.hadoop.hbase.ipc.SimpleRpcServer;
|
||||
import org.apache.hadoop.hbase.security.AccessDeniedException;
|
||||
import org.apache.hadoop.hbase.security.HBaseKerberosUtils;
|
||||
import org.apache.hadoop.hbase.security.SaslUtil;
|
||||
|
@ -83,8 +79,6 @@ import org.apache.hadoop.hbase.security.SecurityInfo;
|
|||
import org.apache.hadoop.hbase.security.User;
|
||||
import org.apache.hadoop.hbase.security.token.SecureTestCluster;
|
||||
import org.apache.hadoop.hbase.security.token.TokenProvider;
|
||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||
import org.apache.hadoop.hbase.testclassification.SecurityTests;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.apache.hadoop.hbase.util.CommonFSUtils;
|
||||
import org.apache.hadoop.hbase.util.Pair;
|
||||
|
@ -100,13 +94,10 @@ import org.apache.hadoop.security.token.TokenIdentifier;
|
|||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameter;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -116,48 +107,30 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.RPCProtos.UserInformati
|
|||
|
||||
/**
|
||||
* Tests the pluggable authentication framework with SASL using a contrived authentication system.
|
||||
*
|
||||
* This tests holds a "user database" in memory as a hashmap. Clients provide their password
|
||||
* in the client Hadoop configuration. The servers validate this password via the "user database".
|
||||
* This tests holds a "user database" in memory as a hashmap. Clients provide their password in the
|
||||
* client Hadoop configuration. The servers validate this password via the "user database".
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
@Category({MediumTests.class, SecurityTests.class})
|
||||
public class TestCustomSaslAuthenticationProvider {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(
|
||||
TestCustomSaslAuthenticationProvider.class);
|
||||
public abstract class CustomSaslAuthenticationProviderTestBase {
|
||||
|
||||
@ClassRule
|
||||
public static final HBaseClassTestRule CLASS_RULE =
|
||||
HBaseClassTestRule.forClass(TestCustomSaslAuthenticationProvider.class);
|
||||
private static final Logger LOG =
|
||||
LoggerFactory.getLogger(CustomSaslAuthenticationProviderTestBase.class);
|
||||
|
||||
private static final Map<String,String> USER_DATABASE = createUserDatabase();
|
||||
private static final Map<String, String> USER_DATABASE = createUserDatabase();
|
||||
|
||||
private static final String USER1_PASSWORD = "foobarbaz";
|
||||
private static final String USER2_PASSWORD = "bazbarfoo";
|
||||
|
||||
@Parameterized.Parameters(name = "{index}: rpcClientImpl={0}, rpcServerImpl={1}")
|
||||
@Parameters
|
||||
public static Collection<Object[]> parameters() {
|
||||
List<Object[]> params = new ArrayList<>();
|
||||
List<String> rpcClientImpls = Arrays.asList(
|
||||
BlockingRpcClient.class.getName(), NettyRpcClient.class.getName());
|
||||
List<String> rpcServerImpls = Arrays.asList(
|
||||
SimpleRpcServer.class.getName(), NettyRpcServer.class.getName());
|
||||
for (String rpcClientImpl : rpcClientImpls) {
|
||||
for (String rpcServerImpl : rpcServerImpls) {
|
||||
params.add(new Object[] { rpcClientImpl, rpcServerImpl });
|
||||
}
|
||||
}
|
||||
return params;
|
||||
return Arrays.asList(new Object[] { BlockingRpcClient.class.getName() },
|
||||
new Object[] { NettyRpcClient.class.getName() });
|
||||
}
|
||||
|
||||
@Parameterized.Parameter(0)
|
||||
@Parameter
|
||||
public String rpcClientImpl;
|
||||
|
||||
@Parameterized.Parameter(1)
|
||||
public String rpcServerImpl;
|
||||
|
||||
private static Map<String,String> createUserDatabase() {
|
||||
Map<String,String> db = new ConcurrentHashMap<>();
|
||||
private static Map<String, String> createUserDatabase() {
|
||||
Map<String, String> db = new ConcurrentHashMap<>();
|
||||
db.put("user1", USER1_PASSWORD);
|
||||
db.put("user2", USER2_PASSWORD);
|
||||
return db;
|
||||
|
@ -172,14 +145,15 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* A custom token identifier for our custom auth'n method. Unique from the TokenIdentifier
|
||||
* used for delegation tokens.
|
||||
* A custom token identifier for our custom auth'n method. Unique from the TokenIdentifier used
|
||||
* for delegation tokens.
|
||||
*/
|
||||
public static class PasswordAuthTokenIdentifier extends TokenIdentifier {
|
||||
public static final Text PASSWORD_AUTH_TOKEN = new Text("HBASE_PASSWORD_TEST_TOKEN");
|
||||
private String username;
|
||||
|
||||
public PasswordAuthTokenIdentifier() {}
|
||||
public PasswordAuthTokenIdentifier() {
|
||||
}
|
||||
|
||||
public PasswordAuthTokenIdentifier(String username) {
|
||||
this.username = username;
|
||||
|
@ -209,29 +183,29 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
}
|
||||
}
|
||||
|
||||
public static Token<? extends TokenIdentifier> createPasswordToken(
|
||||
String username, String password, String clusterId) {
|
||||
public static Token<? extends TokenIdentifier> createPasswordToken(String username,
|
||||
String password, String clusterId) {
|
||||
PasswordAuthTokenIdentifier id = new PasswordAuthTokenIdentifier(username);
|
||||
Token<? extends TokenIdentifier> token = new Token<>(id.getBytes(), Bytes.toBytes(password),
|
||||
id.getKind(), new Text(clusterId));
|
||||
Token<? extends TokenIdentifier> token =
|
||||
new Token<>(id.getBytes(), Bytes.toBytes(password), id.getKind(), new Text(clusterId));
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Client provider that finds custom Token in the user's UGI and authenticates with the server
|
||||
* via DIGEST-MD5 using that password.
|
||||
* Client provider that finds custom Token in the user's UGI and authenticates with the server via
|
||||
* DIGEST-MD5 using that password.
|
||||
*/
|
||||
public static class InMemoryClientProvider extends AbstractSaslClientAuthenticationProvider {
|
||||
public static final String MECHANISM = "DIGEST-MD5";
|
||||
public static final SaslAuthMethod SASL_AUTH_METHOD = new SaslAuthMethod(
|
||||
"IN_MEMORY", (byte)42, MECHANISM, AuthenticationMethod.TOKEN);
|
||||
public static final SaslAuthMethod SASL_AUTH_METHOD =
|
||||
new SaslAuthMethod("IN_MEMORY", (byte) 42, MECHANISM, AuthenticationMethod.TOKEN);
|
||||
|
||||
@Override
|
||||
public SaslClient createClient(Configuration conf, InetAddress serverAddr,
|
||||
SecurityInfo securityInfo, Token<? extends TokenIdentifier> token, boolean fallbackAllowed,
|
||||
Map<String, String> saslProps) throws IOException {
|
||||
SecurityInfo securityInfo, Token<? extends TokenIdentifier> token, boolean fallbackAllowed,
|
||||
Map<String, String> saslProps) throws IOException {
|
||||
return Sasl.createSaslClient(new String[] { MECHANISM }, null, null,
|
||||
SaslUtil.SASL_DEFAULT_REALM, saslProps, new InMemoryClientProviderCallbackHandler(token));
|
||||
SaslUtil.SASL_DEFAULT_REALM, saslProps, new InMemoryClientProviderCallbackHandler(token));
|
||||
}
|
||||
|
||||
public Optional<Token<? extends TokenIdentifier>> findToken(User user) {
|
||||
|
@ -253,11 +227,12 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sasl CallbackHandler which extracts information from our custom token and places
|
||||
* it into the Sasl objects.
|
||||
* Sasl CallbackHandler which extracts information from our custom token and places it into the
|
||||
* Sasl objects.
|
||||
*/
|
||||
public class InMemoryClientProviderCallbackHandler implements CallbackHandler {
|
||||
private final Token<? extends TokenIdentifier> token;
|
||||
|
||||
public InMemoryClientProviderCallbackHandler(Token<? extends TokenIdentifier> token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
@ -302,21 +277,21 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
* Server provider which validates credentials from an in-memory database.
|
||||
*/
|
||||
public static class InMemoryServerProvider extends InMemoryClientProvider
|
||||
implements SaslServerAuthenticationProvider {
|
||||
implements SaslServerAuthenticationProvider {
|
||||
|
||||
@Override
|
||||
public AttemptingUserProvidingSaslServer createServer(
|
||||
SecretManager<TokenIdentifier> secretManager,
|
||||
Map<String, String> saslProps) throws IOException {
|
||||
public AttemptingUserProvidingSaslServer
|
||||
createServer(SecretManager<TokenIdentifier> secretManager, Map<String, String> saslProps)
|
||||
throws IOException {
|
||||
return new AttemptingUserProvidingSaslServer(
|
||||
Sasl.createSaslServer(getSaslAuthMethod().getSaslMechanism(), null,
|
||||
SaslUtil.SASL_DEFAULT_REALM, saslProps, new InMemoryServerProviderCallbackHandler()),
|
||||
Sasl.createSaslServer(getSaslAuthMethod().getSaslMechanism(), null,
|
||||
SaslUtil.SASL_DEFAULT_REALM, saslProps, new InMemoryServerProviderCallbackHandler()),
|
||||
() -> null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulls the correct password for the user who started the SASL handshake so that SASL
|
||||
* can validate that the user provided the right password.
|
||||
* Pulls the correct password for the user who started the SASL handshake so that SASL can
|
||||
* validate that the user provided the right password.
|
||||
*/
|
||||
private class InMemoryServerProviderCallbackHandler implements CallbackHandler {
|
||||
|
||||
|
@ -344,11 +319,11 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
try {
|
||||
id.readFields(new DataInputStream(new ByteArrayInputStream(encodedId)));
|
||||
} catch (IOException e) {
|
||||
throw (InvalidToken) new InvalidToken(
|
||||
"Can't de-serialize tokenIdentifier").initCause(e);
|
||||
throw (InvalidToken) new InvalidToken("Can't de-serialize tokenIdentifier")
|
||||
.initCause(e);
|
||||
}
|
||||
char[] actualPassword = SaslUtil.encodePassword(
|
||||
Bytes.toBytes(getPassword(id.getUser().getUserName())));
|
||||
char[] actualPassword =
|
||||
SaslUtil.encodePassword(Bytes.toBytes(getPassword(id.getUser().getUserName())));
|
||||
pc.setPassword(actualPassword);
|
||||
}
|
||||
if (ac != null) {
|
||||
|
@ -373,7 +348,7 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
|
||||
@Override
|
||||
public UserGroupInformation getAuthorizedUgi(String authzId,
|
||||
SecretManager<TokenIdentifier> secretManager) throws IOException {
|
||||
SecretManager<TokenIdentifier> secretManager) throws IOException {
|
||||
UserGroupInformation authorizedUgi;
|
||||
byte[] encodedId = SaslUtil.decodeIdentifier(authzId);
|
||||
PasswordAuthTokenIdentifier tokenId = new PasswordAuthTokenIdentifier();
|
||||
|
@ -384,8 +359,7 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
}
|
||||
authorizedUgi = tokenId.getUser();
|
||||
if (authorizedUgi == null) {
|
||||
throw new AccessDeniedException(
|
||||
"Can't retrieve username from tokenIdentifier.");
|
||||
throw new AccessDeniedException("Can't retrieve username from tokenIdentifier.");
|
||||
}
|
||||
authorizedUgi.addTokenIdentifier(tokenId);
|
||||
authorizedUgi.setAuthenticationMethod(getSaslAuthMethod().getAuthMethod());
|
||||
|
@ -394,30 +368,28 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Custom provider which can select our custom provider, amongst other tokens which
|
||||
* may be available.
|
||||
* Custom provider which can select our custom provider, amongst other tokens which may be
|
||||
* available.
|
||||
*/
|
||||
public static class InMemoryProviderSelector extends BuiltInProviderSelector {
|
||||
private InMemoryClientProvider inMemoryProvider;
|
||||
|
||||
@Override
|
||||
public void configure(Configuration conf,
|
||||
Collection<SaslClientAuthenticationProvider> providers) {
|
||||
Collection<SaslClientAuthenticationProvider> providers) {
|
||||
super.configure(conf, providers);
|
||||
Optional<SaslClientAuthenticationProvider> o = providers.stream()
|
||||
.filter((p) -> p instanceof InMemoryClientProvider)
|
||||
.findAny();
|
||||
Optional<SaslClientAuthenticationProvider> o =
|
||||
providers.stream().filter((p) -> p instanceof InMemoryClientProvider).findAny();
|
||||
|
||||
inMemoryProvider = (InMemoryClientProvider) o.orElseThrow(
|
||||
() -> new RuntimeException("InMemoryClientProvider not found in available providers: "
|
||||
+ providers));
|
||||
inMemoryProvider = (InMemoryClientProvider) o.orElseThrow(() -> new RuntimeException(
|
||||
"InMemoryClientProvider not found in available providers: " + providers));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<SaslClientAuthenticationProvider, Token<? extends TokenIdentifier>> selectProvider(
|
||||
String clusterId, User user) {
|
||||
public Pair<SaslClientAuthenticationProvider, Token<? extends TokenIdentifier>>
|
||||
selectProvider(String clusterId, User user) {
|
||||
Pair<SaslClientAuthenticationProvider, Token<? extends TokenIdentifier>> superPair =
|
||||
super.selectProvider(clusterId, user);
|
||||
super.selectProvider(clusterId, user);
|
||||
|
||||
Optional<Token<? extends TokenIdentifier>> optional = inMemoryProvider.findToken(user);
|
||||
if (optional.isPresent()) {
|
||||
|
@ -430,21 +402,21 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
}
|
||||
}
|
||||
|
||||
static void createBaseCluster(HBaseTestingUtility util, File keytabFile,
|
||||
MiniKdc kdc) throws Exception {
|
||||
private static void createBaseCluster(HBaseTestingUtility util, File keytabFile, MiniKdc kdc)
|
||||
throws Exception {
|
||||
String servicePrincipal = "hbase/localhost";
|
||||
String spnegoPrincipal = "HTTP/localhost";
|
||||
kdc.createPrincipal(keytabFile, servicePrincipal);
|
||||
util.startMiniZKCluster();
|
||||
|
||||
HBaseKerberosUtils.setSecuredConfiguration(util.getConfiguration(),
|
||||
servicePrincipal + "@" + kdc.getRealm(), spnegoPrincipal + "@" + kdc.getRealm());
|
||||
servicePrincipal + "@" + kdc.getRealm(), spnegoPrincipal + "@" + kdc.getRealm());
|
||||
HBaseKerberosUtils.setSSLConfiguration(util, SecureTestCluster.class);
|
||||
|
||||
util.getConfiguration().setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
|
||||
TokenProvider.class.getName());
|
||||
TokenProvider.class.getName());
|
||||
util.startMiniDFSCluster(1);
|
||||
Path rootdir = util.getDataTestDirOnTestFS("TestGenerateDelegationToken");
|
||||
Path rootdir = util.getDataTestDirOnTestFS("TestCustomSaslAuthenticationProvider");
|
||||
CommonFSUtils.setRootDir(util.getConfiguration(), rootdir);
|
||||
}
|
||||
|
||||
|
@ -453,75 +425,65 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
private static LocalHBaseCluster CLUSTER;
|
||||
private static File KEYTAB_FILE;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupCluster() throws Exception {
|
||||
KEYTAB_FILE = new File(
|
||||
UTIL.getDataTestDir("keytab").toUri().getPath());
|
||||
protected static void startCluster(String rpcServerImpl) throws Exception {
|
||||
KEYTAB_FILE = new File(UTIL.getDataTestDir("keytab").toUri().getPath());
|
||||
final MiniKdc kdc = UTIL.setupMiniKdc(KEYTAB_FILE);
|
||||
|
||||
// Adds our test impls instead of creating service loader entries which
|
||||
// might inadvertently get them loaded on a real cluster.
|
||||
CONF.setStrings(SaslClientAuthenticationProviders.EXTRA_PROVIDERS_KEY,
|
||||
InMemoryClientProvider.class.getName());
|
||||
InMemoryClientProvider.class.getName());
|
||||
CONF.setStrings(SaslServerAuthenticationProviders.EXTRA_PROVIDERS_KEY,
|
||||
InMemoryServerProvider.class.getName());
|
||||
InMemoryServerProvider.class.getName());
|
||||
CONF.set(SaslClientAuthenticationProviders.SELECTOR_KEY,
|
||||
InMemoryProviderSelector.class.getName());
|
||||
InMemoryProviderSelector.class.getName());
|
||||
createBaseCluster(UTIL, KEYTAB_FILE, kdc);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUpBeforeTest() throws Exception {
|
||||
CONF.unset(HConstants.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY);
|
||||
CONF.set(RpcClientFactory.CUSTOM_RPC_CLIENT_IMPL_CONF_KEY, rpcClientImpl);
|
||||
CONF.set(RpcServerFactory.CUSTOM_RPC_SERVER_IMPL_CONF_KEY, rpcServerImpl);
|
||||
if (rpcClientImpl.equals(BlockingRpcClient.class.getName())) {
|
||||
// Set the connection registry to ZKConnectionRegistry since hedging is not supported on
|
||||
// blocking rpc clients.
|
||||
CONF.set(HConstants.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY,
|
||||
HConstants.ZK_CONNECTION_REGISTRY_CLASS);
|
||||
}
|
||||
CLUSTER = new LocalHBaseCluster(CONF, 1);
|
||||
CLUSTER.startup();
|
||||
createTable();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void teardownCluster() throws Exception {
|
||||
public static void shutdownCluster() throws Exception {
|
||||
if (CLUSTER != null) {
|
||||
CLUSTER.shutdown();
|
||||
CLUSTER = null;
|
||||
}
|
||||
UTIL.shutdownMiniDFSCluster();
|
||||
UTIL.shutdownMiniZKCluster();
|
||||
UTIL.cleanupTestDir();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
createTable();
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutDownCluster() throws IOException {
|
||||
if (CLUSTER != null) {
|
||||
UTIL.deleteTable(name.getTableName());
|
||||
CLUSTER.shutdown();
|
||||
}
|
||||
public void tearDown() throws IOException {
|
||||
UTIL.deleteTable(name.getTableName());
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TableNameTestRule name = new TableNameTestRule();
|
||||
TableName tableName;
|
||||
String clusterId;
|
||||
|
||||
public void createTable() throws Exception {
|
||||
private TableName tableName;
|
||||
|
||||
private String clusterId;
|
||||
|
||||
private void createTable() throws Exception {
|
||||
tableName = name.getTableName();
|
||||
|
||||
// Create a table and write a record as the service user (hbase)
|
||||
UserGroupInformation serviceUgi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(
|
||||
"hbase/localhost", KEYTAB_FILE.getAbsolutePath());
|
||||
UserGroupInformation serviceUgi = UserGroupInformation
|
||||
.loginUserFromKeytabAndReturnUGI("hbase/localhost", KEYTAB_FILE.getAbsolutePath());
|
||||
clusterId = serviceUgi.doAs(new PrivilegedExceptionAction<String>() {
|
||||
@Override public String run() throws Exception {
|
||||
@Override
|
||||
public String run() throws Exception {
|
||||
try (Connection conn = ConnectionFactory.createConnection(CONF);
|
||||
Admin admin = conn.getAdmin();) {
|
||||
admin.createTable(TableDescriptorBuilder
|
||||
.newBuilder(tableName)
|
||||
.setColumnFamily(ColumnFamilyDescriptorBuilder.of("f1"))
|
||||
.build());
|
||||
Admin admin = conn.getAdmin();) {
|
||||
admin.createTable(TableDescriptorBuilder.newBuilder(tableName)
|
||||
.setColumnFamily(ColumnFamilyDescriptorBuilder.of("f1")).build());
|
||||
|
||||
UTIL.waitTableAvailable(tableName);
|
||||
|
||||
|
@ -535,21 +497,25 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
assertNotNull(clusterId);
|
||||
}
|
||||
|
||||
private Configuration getClientConf() {
|
||||
Configuration conf = new Configuration(CONF);
|
||||
conf.set(RpcClientFactory.CUSTOM_RPC_CLIENT_IMPL_CONF_KEY, rpcClientImpl);
|
||||
return conf;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPositiveAuthentication() throws Exception {
|
||||
// Validate that we can read that record back out as the user with our custom auth'n
|
||||
final Configuration clientConf = new Configuration(CONF);
|
||||
UserGroupInformation user1 = UserGroupInformation.createUserForTesting(
|
||||
"user1", new String[0]);
|
||||
UserGroupInformation user1 = UserGroupInformation.createUserForTesting("user1", new String[0]);
|
||||
user1.addToken(createPasswordToken("user1", USER1_PASSWORD, clusterId));
|
||||
user1.doAs(new PrivilegedExceptionAction<Void>() {
|
||||
@Override public Void run() throws Exception {
|
||||
try (Connection conn = ConnectionFactory.createConnection(clientConf);
|
||||
Table t = conn.getTable(tableName)) {
|
||||
@Override
|
||||
public Void run() throws Exception {
|
||||
try (Connection conn = ConnectionFactory.createConnection(getClientConf());
|
||||
Table t = conn.getTable(tableName)) {
|
||||
Result r = t.get(new Get(Bytes.toBytes("r1")));
|
||||
assertNotNull(r);
|
||||
assertFalse("Should have read a non-empty Result", r.isEmpty());
|
||||
|
@ -565,20 +531,20 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
@Test
|
||||
public void testNegativeAuthentication() throws Exception {
|
||||
// Validate that we can read that record back out as the user with our custom auth'n
|
||||
final Configuration clientConf = new Configuration(CONF);
|
||||
clientConf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 3);
|
||||
UserGroupInformation user1 = UserGroupInformation.createUserForTesting(
|
||||
"user1", new String[0]);
|
||||
UserGroupInformation user1 = UserGroupInformation.createUserForTesting("user1", new String[0]);
|
||||
user1.addToken(createPasswordToken("user1", "definitely not the password", clusterId));
|
||||
user1.doAs(new PrivilegedExceptionAction<Void>() {
|
||||
@Override public Void run() throws Exception {
|
||||
@Override
|
||||
public Void run() throws Exception {
|
||||
Configuration clientConf = getClientConf();
|
||||
clientConf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
|
||||
// Depending on the registry in use, the following code can throw exceptions at different
|
||||
// places. Master registry fails at the createConnection() step because the RPC to the
|
||||
// master fails with sasl auth. With ZK registry, connection creation succeeds (since there
|
||||
// is no RPC to HBase services involved) but the subsequent get() fails. The root cause
|
||||
// should still be a SaslException in both the cases.
|
||||
try (Connection conn = ConnectionFactory.createConnection(clientConf);
|
||||
Table t = conn.getTable(tableName)) {
|
||||
Table t = conn.getTable(tableName)) {
|
||||
t.get(new Get(Bytes.toBytes("r1")));
|
||||
fail("Should not successfully authenticate with HBase");
|
||||
} catch (MasterRegistryFetchException mfe) {
|
||||
|
@ -588,8 +554,8 @@ public class TestCustomSaslAuthenticationProvider {
|
|||
assertTrue(re.getMessage(), re.getMessage().contains("SaslException"));
|
||||
} catch (Exception e) {
|
||||
// Any other exception is unexpected.
|
||||
fail("Unexpected exception caught, was expecting a authentication error: "
|
||||
+ Throwables.getStackTraceAsString(e));
|
||||
fail("Unexpected exception caught, was expecting a authentication error: " +
|
||||
Throwables.getStackTraceAsString(e));
|
||||
}
|
||||
return null;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* 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.provider;
|
||||
|
||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||
import org.apache.hadoop.hbase.ipc.NettyRpcServer;
|
||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||
import org.apache.hadoop.hbase.testclassification.SecurityTests;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
@Category({ MediumTests.class, SecurityTests.class })
|
||||
public class TestCustomSaslAuthenticationProviderNettyRpcServer
|
||||
extends CustomSaslAuthenticationProviderTestBase {
|
||||
|
||||
@ClassRule
|
||||
public static final HBaseClassTestRule CLASS_RULE =
|
||||
HBaseClassTestRule.forClass(TestCustomSaslAuthenticationProviderNettyRpcServer.class);
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
startCluster(NettyRpcServer.class.getName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* 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.provider;
|
||||
|
||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||
import org.apache.hadoop.hbase.ipc.SimpleRpcServer;
|
||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||
import org.apache.hadoop.hbase.testclassification.SecurityTests;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
@Category({ MediumTests.class, SecurityTests.class })
|
||||
public class TestCustomSaslAuthenticationProviderSimpleRpcServer
|
||||
extends CustomSaslAuthenticationProviderTestBase {
|
||||
|
||||
@ClassRule
|
||||
public static final HBaseClassTestRule CLASS_RULE =
|
||||
HBaseClassTestRule.forClass(TestCustomSaslAuthenticationProviderSimpleRpcServer.class);
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
startCluster(SimpleRpcServer.class.getName());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue