use of org.apache.hadoop.ozone.security.OzoneTokenIdentifier in project ozone by apache.
the class OzoneClientFactory method getOzoneClient.
/**
* Create OzoneClient for token renew/cancel operations.
* @param conf Configuration to be used for OzoneCient creation
* @param token ozone token is involved
* @return
* @throws IOException
*/
public static OzoneClient getOzoneClient(Configuration conf, Token<OzoneTokenIdentifier> token) throws IOException {
Preconditions.checkNotNull(token, "Null token is not allowed");
OzoneTokenIdentifier tokenId = new OzoneTokenIdentifier();
ByteArrayInputStream buf = new ByteArrayInputStream(token.getIdentifier());
DataInputStream in = new DataInputStream(buf);
tokenId.readFields(in);
String omServiceId = tokenId.getOmServiceId();
OzoneConfiguration ozoneConf = OzoneConfiguration.of(conf);
// Must check with OzoneConfiguration so that ozone-site.xml is loaded.
if (StringUtils.isNotEmpty(omServiceId)) {
// new OM should always issue token with omServiceId
if (!OmUtils.isServiceIdsDefined(ozoneConf) && omServiceId.equals(OzoneConsts.OM_SERVICE_ID_DEFAULT)) {
// Non-HA or single-node Ratis HA
return OzoneClientFactory.getRpcClient(ozoneConf);
} else if (OmUtils.isOmHAServiceId(ozoneConf, omServiceId)) {
// HA with matching service id
return OzoneClientFactory.getRpcClient(omServiceId, ozoneConf);
} else {
// HA with mismatched service id
throw new IOException("Service ID specified " + omServiceId + " does not match" + " with " + OZONE_OM_SERVICE_IDS_KEY + " defined in the " + "configuration. Configured " + OZONE_OM_SERVICE_IDS_KEY + " are" + ozoneConf.getTrimmedStringCollection(OZONE_OM_SERVICE_IDS_KEY));
}
} else {
// with non-HA case
if (!OmUtils.isServiceIdsDefined(ozoneConf)) {
return OzoneClientFactory.getRpcClient(ozoneConf);
} else {
throw new IOException("OzoneToken with no service ID can't " + "be renewed or canceled with local OM HA setup because we " + "don't know if the token is issued from local OM HA cluster " + "or not.");
}
}
}
use of org.apache.hadoop.ozone.security.OzoneTokenIdentifier in project ozone by apache.
the class OzoneManager method cancelDelegationToken.
/**
* Cancels a delegation token.
*
* @param token token to cancel
* @throws IOException on error
*/
@Override
public void cancelDelegationToken(Token<OzoneTokenIdentifier> token) throws OMException {
OzoneTokenIdentifier id = null;
try {
String canceller = getRemoteUser().getUserName();
id = delegationTokenMgr.cancelToken(token, canceller);
LOG.trace("Delegation token cancelled for dt: {}", id);
} catch (OMException oex) {
throw oex;
} catch (IOException ex) {
LOG.error("Delegation token cancellation failed for dt id: {}, cause: {}", id, ex.getMessage());
throw new OMException("Delegation token renewal failed for dt: " + token, ex, TOKEN_ERROR_OTHER);
}
}
use of org.apache.hadoop.ozone.security.OzoneTokenIdentifier in project ozone by apache.
the class TestSecureOzoneCluster method testDelegationTokenRenewal.
/**
* Tests delegation token renewal.
*/
@Test
public void testDelegationTokenRenewal() throws Exception {
GenericTestUtils.setLogLevel(LoggerFactory.getLogger(Server.class.getName()), INFO);
LogCapturer omLogs = LogCapturer.captureLogs(OzoneManager.getLogger());
// Setup secure OM for start.
OzoneConfiguration newConf = new OzoneConfiguration(conf);
int tokenMaxLifetime = 1000;
newConf.setLong(DELEGATION_TOKEN_MAX_LIFETIME_KEY, tokenMaxLifetime);
setupOm(newConf);
OzoneManager.setTestSecureOmFlag(true);
try {
om.setCertClient(new CertificateClientTestImpl(conf));
om.start();
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
// Get first OM client which will authenticate via Kerberos
omClient = new OzoneManagerProtocolClientSideTranslatorPB(OmTransportFactory.create(conf, ugi, null), RandomStringUtils.randomAscii(5));
// Since client is already connected get a delegation token
Token<OzoneTokenIdentifier> token = omClient.getDelegationToken(new Text("om"));
// Check if token is of right kind and renewer is running om instance
assertNotNull(token);
assertEquals("OzoneToken", token.getKind().toString());
assertEquals(OmUtils.getOmRpcAddress(conf), token.getService().toString());
// Renew delegation token
long expiryTime = omClient.renewDelegationToken(token);
assertTrue(expiryTime > 0);
omLogs.clearOutput();
// Test failure of delegation renewal
// 1. When token maxExpiryTime exceeds
Thread.sleep(tokenMaxLifetime);
OMException ex = LambdaTestUtils.intercept(OMException.class, "TOKEN_EXPIRED", () -> omClient.renewDelegationToken(token));
assertEquals(TOKEN_EXPIRED, ex.getResult());
omLogs.clearOutput();
// 2. When renewer doesn't match (implicitly covers when renewer is
// null or empty )
Token<OzoneTokenIdentifier> token2 = omClient.getDelegationToken(new Text("randomService"));
assertNotNull(token2);
LambdaTestUtils.intercept(OMException.class, "Delegation token renewal failed", () -> omClient.renewDelegationToken(token2));
assertTrue(omLogs.getOutput().contains(" with non-matching " + "renewer randomService"));
omLogs.clearOutput();
// 3. Test tampered token
OzoneTokenIdentifier tokenId = OzoneTokenIdentifier.readProtoBuf(token.getIdentifier());
tokenId.setRenewer(new Text("om"));
tokenId.setMaxDate(System.currentTimeMillis() * 2);
Token<OzoneTokenIdentifier> tamperedToken = new Token<>(tokenId.getBytes(), token2.getPassword(), token2.getKind(), token2.getService());
LambdaTestUtils.intercept(OMException.class, "Delegation token renewal failed", () -> omClient.renewDelegationToken(tamperedToken));
assertTrue(omLogs.getOutput().contains("can't be found in " + "cache"));
omLogs.clearOutput();
} finally {
om.stop();
om.join();
}
}
use of org.apache.hadoop.ozone.security.OzoneTokenIdentifier in project ozone by apache.
the class TestDelegationToken method testDelegationToken.
/**
* Performs following tests for delegation token.
* 1. Get valid delegation token
* 2. Test successful token renewal.
* 3. Client can authenticate using token.
* 4. Delegation token renewal without Kerberos auth fails.
* 5. Test success of token cancellation.
* 5. Test failure of token cancellation.
*/
@Test
public void testDelegationToken() throws Exception {
// Capture logs for assertions
LogCapturer logs = LogCapturer.captureLogs(Server.AUDITLOG);
LogCapturer omLogs = LogCapturer.captureLogs(OzoneManager.getLogger());
GenericTestUtils.setLogLevel(LoggerFactory.getLogger(Server.class.getName()), INFO);
// Setup secure OM for start
setupOm(conf);
// These are two very important lines: ProtobufRpcEngine uses ClientCache
// which caches clients until no more references. Cache key is the
// SocketFactory which means that we use one Client instance for
// all the Hadoop RPC.
//
// Hadoop Client caches connections with a connection pool. Even if you
// close the client here, if you have ANY Hadoop RPC clients which uses the
// same Client, connections can be reused.
//
// Here we closed all the OTHER Hadoop RPC clients to have only the clients
// from this unit test.
//
// With this approach all the following client.close() calls trigger a
// Client.close (if there is no other open Hadoop RPC client) which triggers
// connection close for all the available connection.
//
// The following test tests the authorization of the new client calls, it
// requires a real connection close and connection open as the authorization
// is part the initial handhsake of Hadoop RPC.
om.getScmClient().getBlockClient().close();
om.getScmClient().getContainerClient().close();
try {
// Start OM
om.setCertClient(new CertificateClientTestImpl(conf));
om.start();
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
String username = ugi.getUserName();
// Get first OM client which will authenticate via Kerberos
omClient = new OzoneManagerProtocolClientSideTranslatorPB(OmTransportFactory.create(conf, ugi, null), RandomStringUtils.randomAscii(5));
// Assert if auth was successful via Kerberos
assertFalse(logs.getOutput().contains("Auth successful for " + username + " (auth:KERBEROS)"));
// Case 1: Test successful delegation token.
Token<OzoneTokenIdentifier> token = omClient.getDelegationToken(new Text("om"));
// Case 2: Test successful token renewal.
long renewalTime = omClient.renewDelegationToken(token);
assertTrue(renewalTime > 0);
// Check if token is of right kind and renewer is running om instance
assertNotNull(token);
assertEquals("OzoneToken", token.getKind().toString());
assertEquals(OmUtils.getOmRpcAddress(conf), token.getService().toString());
omClient.close();
// Create a remote ugi and set its authentication method to Token
UserGroupInformation testUser = UserGroupInformation.createRemoteUser(TEST_USER);
testUser.addToken(token);
testUser.setAuthenticationMethod(AuthMethod.TOKEN);
UserGroupInformation.setLoginUser(testUser);
// Get Om client, this time authentication should happen via Token
testUser.doAs((PrivilegedExceptionAction<Void>) () -> {
omClient = new OzoneManagerProtocolClientSideTranslatorPB(OmTransportFactory.create(conf, testUser, null), RandomStringUtils.randomAscii(5));
return null;
});
// Case 3: Test Client can authenticate using token.
assertFalse(logs.getOutput().contains("Auth successful for " + username + " (auth:TOKEN)"));
OzoneTestUtils.expectOmException(VOLUME_NOT_FOUND, () -> omClient.deleteVolume("vol1"));
assertTrue("Log file doesn't contain successful auth for user " + username, logs.getOutput().contains("Auth successful for " + username + " (auth:TOKEN)"));
// Case 4: Test failure of token renewal.
// Call to renewDelegationToken will fail but it will confirm that
// initial connection via DT succeeded
omLogs.clearOutput();
OMException ex = LambdaTestUtils.intercept(OMException.class, "INVALID_AUTH_METHOD", () -> omClient.renewDelegationToken(token));
assertEquals(INVALID_AUTH_METHOD, ex.getResult());
assertTrue(logs.getOutput().contains("Auth successful for " + username + " (auth:TOKEN)"));
omLogs.clearOutput();
// testUser.setAuthenticationMethod(AuthMethod.KERBEROS);
omClient.close();
UserGroupInformation.setLoginUser(ugi);
omClient = new OzoneManagerProtocolClientSideTranslatorPB(OmTransportFactory.create(conf, ugi, null), RandomStringUtils.randomAscii(5));
// Case 5: Test success of token cancellation.
omClient.cancelDelegationToken(token);
omClient.close();
// Wait for client to timeout
Thread.sleep(CLIENT_TIMEOUT);
assertFalse(logs.getOutput().contains("Auth failed for"));
// Case 6: Test failure of token cancellation.
// Get Om client, this time authentication using Token will fail as
// token is not in cache anymore.
omClient = new OzoneManagerProtocolClientSideTranslatorPB(OmTransportFactory.create(conf, testUser, null), RandomStringUtils.randomAscii(5));
ex = LambdaTestUtils.intercept(OMException.class, "Cancel delegation token failed", () -> omClient.cancelDelegationToken(token));
assertEquals(TOKEN_ERROR_OTHER, ex.getResult());
assertTrue(logs.getOutput().contains("Auth failed for"));
} finally {
om.stop();
om.join();
}
}
use of org.apache.hadoop.ozone.security.OzoneTokenIdentifier in project ozone by apache.
the class OMCancelDelegationTokenRequest method validateAndUpdateCache.
@Override
public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, long transactionLogIndex, OzoneManagerDoubleBufferHelper ozoneManagerDoubleBufferHelper) {
OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
OMClientResponse omClientResponse = null;
OMResponse.Builder omResponse = OmResponseUtil.getOMResponseBuilder(getOmRequest());
OzoneTokenIdentifier ozoneTokenIdentifier = null;
try {
ozoneTokenIdentifier = OzoneTokenIdentifier.readProtoBuf(getToken().getIdentifier());
// Remove token from in-memory.
ozoneManager.getDelegationTokenMgr().removeToken(ozoneTokenIdentifier);
// Update Cache.
omMetadataManager.getDelegationTokenTable().addCacheEntry(new CacheKey<>(ozoneTokenIdentifier), new CacheValue<>(Optional.absent(), transactionLogIndex));
omClientResponse = new OMCancelDelegationTokenResponse(ozoneTokenIdentifier, omResponse.setCancelDelegationTokenResponse(CancelDelegationTokenResponseProto.newBuilder().setResponse(SecurityProtos.CancelDelegationTokenResponseProto.newBuilder())).build());
} catch (IOException ex) {
LOG.error("Error in cancel DelegationToken {}", ozoneTokenIdentifier, ex);
omClientResponse = new OMCancelDelegationTokenResponse(null, createErrorOMResponse(omResponse, ex));
} finally {
addResponseToDoubleBuffer(transactionLogIndex, omClientResponse, ozoneManagerDoubleBufferHelper);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Cancelled delegation token: {}", ozoneTokenIdentifier);
}
return omClientResponse;
}
Aggregations