use of org.apache.kafka.common.security.auth.SecurityProtocol in project apache-kafka-on-k8s by banzaicloud.
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 apache-kafka-on-k8s by banzaicloud.
the class SslTransportLayerTest method testEndpointIdentificationDisabled.
/**
* Tests that server certificate with invalid IP address is accepted by
* a client that has disabled endpoint validation
*/
@Test
public void testEndpointIdentificationDisabled() throws Exception {
String node = "0";
String serverHost = InetAddress.getLocalHost().getHostAddress();
SecurityProtocol securityProtocol = SecurityProtocol.SSL;
server = new NioEchoServer(ListenerName.forSecurityProtocol(securityProtocol), securityProtocol, new TestSecurityConfig(sslServerConfigs), serverHost, null, null);
server.start();
sslClientConfigs.remove(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG);
createSelector(sslClientConfigs);
InetSocketAddress addr = new InetSocketAddress(serverHost, server.port());
selector.connect(node, addr, BUFFER_SIZE, BUFFER_SIZE);
NetworkTestUtils.checkClientConnection(selector, node, 100, 10);
}
use of org.apache.kafka.common.security.auth.SecurityProtocol in project apache-kafka-on-k8s by banzaicloud.
the class SslTransportLayerTest method testServerKeystoreDynamicUpdate.
/**
* Tests reconfiguration of server keystore. Verifies that existing connections continue
* to work with old keystore and new connections work with new keystore.
*/
@Test
public void testServerKeystoreDynamicUpdate() throws Exception {
SecurityProtocol securityProtocol = SecurityProtocol.SSL;
TestSecurityConfig config = new TestSecurityConfig(sslServerConfigs);
ListenerName listenerName = ListenerName.forSecurityProtocol(securityProtocol);
ChannelBuilder serverChannelBuilder = ChannelBuilders.serverChannelBuilder(listenerName, false, securityProtocol, config, null, null);
server = new NioEchoServer(listenerName, securityProtocol, config, "localhost", serverChannelBuilder, null);
server.start();
InetSocketAddress addr = new InetSocketAddress("localhost", server.port());
// Verify that client with matching truststore can authenticate, send and receive
String oldNode = "0";
Selector oldClientSelector = createSelector(sslClientConfigs);
oldClientSelector.connect(oldNode, addr, BUFFER_SIZE, BUFFER_SIZE);
NetworkTestUtils.checkClientConnection(selector, oldNode, 100, 10);
CertStores newServerCertStores = new CertStores(true, "server", "localhost");
sslServerConfigs = newServerCertStores.getTrustingConfig(clientCertStores);
assertTrue("SslChannelBuilder not reconfigurable", serverChannelBuilder instanceof ListenerReconfigurable);
ListenerReconfigurable reconfigurableBuilder = (ListenerReconfigurable) serverChannelBuilder;
assertEquals(listenerName, reconfigurableBuilder.listenerName());
reconfigurableBuilder.validateReconfiguration(sslServerConfigs);
reconfigurableBuilder.reconfigure(sslServerConfigs);
// Verify that new client with old truststore fails
oldClientSelector.connect("1", addr, BUFFER_SIZE, BUFFER_SIZE);
NetworkTestUtils.waitForChannelClose(oldClientSelector, "1", ChannelState.State.AUTHENTICATION_FAILED);
// Verify that new client with new truststore can authenticate, send and receive
sslClientConfigs = clientCertStores.getTrustingConfig(newServerCertStores);
Selector newClientSelector = createSelector(sslClientConfigs);
newClientSelector.connect("2", addr, BUFFER_SIZE, BUFFER_SIZE);
NetworkTestUtils.checkClientConnection(newClientSelector, "2", 100, 10);
// Verify that old client continues to work
NetworkTestUtils.checkClientConnection(oldClientSelector, oldNode, 100, 10);
CertStores invalidCertStores = new CertStores(true, "server", "127.0.0.1");
Map<String, Object> invalidConfigs = invalidCertStores.getTrustingConfig(clientCertStores);
try {
reconfigurableBuilder.validateReconfiguration(invalidConfigs);
fail("Should have failed validation with an exception with different SubjectAltName");
} catch (KafkaException e) {
// expected exception
}
try {
reconfigurableBuilder.reconfigure(invalidConfigs);
fail("Should have failed to reconfigure with different SubjectAltName");
} catch (KafkaException e) {
// expected exception
}
// Verify that new connections continue to work with the server with previously configured keystore after failed reconfiguration
newClientSelector.connect("3", addr, BUFFER_SIZE, BUFFER_SIZE);
NetworkTestUtils.checkClientConnection(newClientSelector, "3", 100, 10);
}
Aggregations