use of org.apache.kafka.common.security.auth.SecurityProtocol in project kafka by apache.
the class SaslAuthenticatorTest method testClientLoginOverride.
/**
* Tests SASL login class override.
*/
@Test
public void testClientLoginOverride() throws Exception {
SecurityProtocol securityProtocol = SecurityProtocol.SASL_PLAINTEXT;
TestJaasConfig jaasConfig = configureMechanisms("PLAIN", Collections.singletonList("PLAIN"));
jaasConfig.setClientOptions("PLAIN", "invaliduser", "invalidpassword");
server = createEchoServer(securityProtocol);
// Connection should succeed using login override that sets correct username/password in Subject
saslClientConfigs.put(SaslConfigs.SASL_LOGIN_CLASS, TestLogin.class.getName());
createAndCheckClientConnection(securityProtocol, "1");
assertEquals(1, TestLogin.loginCount.get());
// Connection should fail without login override since username/password in jaas config is invalid
saslClientConfigs.remove(SaslConfigs.SASL_LOGIN_CLASS);
createAndCheckClientConnectionFailure(securityProtocol, "invalid");
assertEquals(1, TestLogin.loginCount.get());
}
use of org.apache.kafka.common.security.auth.SecurityProtocol in project kafka by apache.
the class SaslAuthenticatorTest method testUnauthenticatedApiVersionsRequest.
/**
* Tests that Kafka ApiVersionsRequests are handled by the SASL server authenticator
* prior to SASL handshake flow and that subsequent authentication succeeds
* when transport layer is PLAINTEXT/SSL. This test uses a non-SASL client that simulates
* SASL authentication after ApiVersionsRequest.
* <p>
* Test sequence (using <tt>securityProtocol=PLAINTEXT</tt> as an example):
* <ol>
* <li>Starts a SASL_PLAINTEXT test server that simply echoes back client requests after authentication.</li>
* <li>A (non-SASL) PLAINTEXT test client connects to the SASL server port. Client is now unauthenticated.<./li>
* <li>The unauthenticated non-SASL client sends an ApiVersionsRequest and validates the response.
* A valid response indicates that {@link SaslServerAuthenticator} of the test server responded to
* the ApiVersionsRequest even though the client is not yet authenticated.</li>
* <li>The unauthenticated non-SASL client sends a SaslHandshakeRequest and validates the response. A valid response
* indicates that {@link SaslServerAuthenticator} of the test server responded to the SaslHandshakeRequest
* after processing ApiVersionsRequest.</li>
* <li>The unauthenticated non-SASL client sends the SASL/PLAIN packet containing username/password to authenticate
* itself. The client is now authenticated by the server. At this point this test client is at the
* same state as a regular SASL_PLAINTEXT client that is <tt>ready</tt>.</li>
* <li>The authenticated client sends random data to the server and checks that the data is echoed
* back by the test server (ie, not Kafka request-response) to ensure that the client now
* behaves exactly as a regular SASL_PLAINTEXT client that has completed authentication.</li>
* </ol>
*/
private void testUnauthenticatedApiVersionsRequest(SecurityProtocol securityProtocol, short saslHandshakeVersion) throws Exception {
configureMechanisms("PLAIN", Arrays.asList("PLAIN"));
server = createEchoServer(securityProtocol);
// Create non-SASL connection to manually authenticate after ApiVersionsRequest
String node = "1";
SecurityProtocol clientProtocol;
switch(securityProtocol) {
case SASL_PLAINTEXT:
clientProtocol = SecurityProtocol.PLAINTEXT;
break;
case SASL_SSL:
clientProtocol = SecurityProtocol.SSL;
break;
default:
throw new IllegalArgumentException("Server protocol " + securityProtocol + " is not SASL");
}
createClientConnection(clientProtocol, node);
NetworkTestUtils.waitForChannelReady(selector, node);
// Send ApiVersionsRequest and check response
ApiVersionsResponse versionsResponse = sendVersionRequestReceiveResponse(node);
assertEquals(ApiKeys.SASL_HANDSHAKE.oldestVersion(), versionsResponse.apiVersion(ApiKeys.SASL_HANDSHAKE.id).minVersion());
assertEquals(ApiKeys.SASL_HANDSHAKE.latestVersion(), versionsResponse.apiVersion(ApiKeys.SASL_HANDSHAKE.id).maxVersion());
assertEquals(ApiKeys.SASL_AUTHENTICATE.oldestVersion(), versionsResponse.apiVersion(ApiKeys.SASL_AUTHENTICATE.id).minVersion());
assertEquals(ApiKeys.SASL_AUTHENTICATE.latestVersion(), versionsResponse.apiVersion(ApiKeys.SASL_AUTHENTICATE.id).maxVersion());
// Send SaslHandshakeRequest and check response
SaslHandshakeResponse handshakeResponse = sendHandshakeRequestReceiveResponse(node, saslHandshakeVersion);
assertEquals(Collections.singletonList("PLAIN"), handshakeResponse.enabledMechanisms());
// Complete manual authentication and check send/receive succeed
authenticateUsingSaslPlainAndCheckConnection(node, saslHandshakeVersion > 0);
}
use of org.apache.kafka.common.security.auth.SecurityProtocol in project kafka by apache.
the class SaslAuthenticatorTest method testCannotReauthenticateAgainFasterThanOneSecond.
/**
* Second re-authentication must fail if it is sooner than one second after the first
*/
@Test
public void testCannotReauthenticateAgainFasterThanOneSecond() throws Exception {
String node = "0";
time = new MockTime();
SecurityProtocol securityProtocol = SecurityProtocol.SASL_SSL;
configureMechanisms(OAuthBearerLoginModule.OAUTHBEARER_MECHANISM, Arrays.asList(OAuthBearerLoginModule.OAUTHBEARER_MECHANISM));
server = createEchoServer(securityProtocol);
try {
createClientConnection(securityProtocol, node);
checkClientConnection(node);
server.verifyAuthenticationMetrics(1, 0);
server.verifyReauthenticationMetrics(0, 0);
/*
* Now sleep long enough so that the next write will cause re-authentication,
* which we expect to succeed.
*/
time.sleep((long) (CONNECTIONS_MAX_REAUTH_MS_VALUE * 1.1));
checkClientConnection(node);
server.verifyAuthenticationMetrics(1, 0);
server.verifyReauthenticationMetrics(1, 0);
/*
* Now sleep long enough so that the next write will cause re-authentication,
* but this time we expect re-authentication to not occur since it has been too
* soon. The checkClientConnection() call should return an error saying it
* expected the one byte-plus-node response but got the SaslHandshakeRequest
* instead
*/
time.sleep((long) (CONNECTIONS_MAX_REAUTH_MS_VALUE * 1.1));
AssertionFailedError exception = assertThrows(AssertionFailedError.class, () -> NetworkTestUtils.checkClientConnection(selector, node, 1, 1));
String expectedResponseTextRegex = "\\w-" + node;
String receivedResponseTextRegex = ".*" + OAuthBearerLoginModule.OAUTHBEARER_MECHANISM;
assertTrue(exception.getMessage().matches(".*<" + expectedResponseTextRegex + ">.*<" + receivedResponseTextRegex + ".*?>"), "Should have received the SaslHandshakeRequest bytes back since we re-authenticated too quickly, " + "but instead we got our generated message echoed back, implying re-auth succeeded when it should not have: " + exception);
// unchanged
server.verifyReauthenticationMetrics(1, 0);
} finally {
selector.close();
selector = null;
}
}
use of org.apache.kafka.common.security.auth.SecurityProtocol in project kafka by apache.
the class SaslAuthenticatorTest method testInvalidUsernameSaslPlain.
/**
* Tests that SASL/PLAIN clients with invalid username fail authentication.
*/
@Test
public void testInvalidUsernameSaslPlain() throws Exception {
String node = "0";
SecurityProtocol securityProtocol = SecurityProtocol.SASL_SSL;
TestJaasConfig jaasConfig = configureMechanisms("PLAIN", Arrays.asList("PLAIN"));
jaasConfig.setClientOptions("PLAIN", "invaliduser", TestJaasConfig.PASSWORD);
server = createEchoServer(securityProtocol);
createAndCheckClientAuthenticationFailure(securityProtocol, node, "PLAIN", "Authentication failed: Invalid username or password");
server.verifyAuthenticationMetrics(0, 1);
server.verifyReauthenticationMetrics(0, 0);
}
use of org.apache.kafka.common.security.auth.SecurityProtocol in project kafka by apache.
the class SaslAuthenticatorTest method testClientAuthenticateCallbackHandler.
/**
* Tests SASL client authentication callback handler override.
*/
@Test
public void testClientAuthenticateCallbackHandler() throws Exception {
SecurityProtocol securityProtocol = SecurityProtocol.SASL_PLAINTEXT;
TestJaasConfig jaasConfig = configureMechanisms("PLAIN", Collections.singletonList("PLAIN"));
saslClientConfigs.put(SaslConfigs.SASL_CLIENT_CALLBACK_HANDLER_CLASS, TestClientCallbackHandler.class.getName());
// remove username, password in login context
jaasConfig.setClientOptions("PLAIN", "", "");
Map<String, Object> options = new HashMap<>();
options.put("user_" + TestClientCallbackHandler.USERNAME, TestClientCallbackHandler.PASSWORD);
jaasConfig.createOrUpdateEntry(TestJaasConfig.LOGIN_CONTEXT_SERVER, PlainLoginModule.class.getName(), options);
server = createEchoServer(securityProtocol);
createAndCheckClientConnection(securityProtocol, "good");
options.clear();
options.put("user_" + TestClientCallbackHandler.USERNAME, "invalid-password");
jaasConfig.createOrUpdateEntry(TestJaasConfig.LOGIN_CONTEXT_SERVER, PlainLoginModule.class.getName(), options);
createAndCheckClientConnectionFailure(securityProtocol, "invalid");
}
Aggregations