Search in sources :

Example 31 with SecurityProtocol

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);
}
Also used : ApiVersionsResponse(org.apache.kafka.common.requests.ApiVersionsResponse) SaslHandshakeResponse(org.apache.kafka.common.requests.SaslHandshakeResponse) SecurityProtocol(org.apache.kafka.common.security.auth.SecurityProtocol)

Example 32 with SecurityProtocol

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);
}
Also used : InetSocketAddress(java.net.InetSocketAddress) SecurityProtocol(org.apache.kafka.common.security.auth.SecurityProtocol) TestSecurityConfig(org.apache.kafka.common.security.TestSecurityConfig) Test(org.junit.Test)

Example 33 with SecurityProtocol

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);
}
Also used : InetSocketAddress(java.net.InetSocketAddress) SecurityProtocol(org.apache.kafka.common.security.auth.SecurityProtocol) TestSecurityConfig(org.apache.kafka.common.security.TestSecurityConfig) KafkaException(org.apache.kafka.common.KafkaException) Test(org.junit.Test)

Aggregations

SecurityProtocol (org.apache.kafka.common.security.auth.SecurityProtocol)33 Test (org.junit.Test)29 HashMap (java.util.HashMap)8 InetSocketAddress (java.net.InetSocketAddress)5 RequestHeader (org.apache.kafka.common.requests.RequestHeader)4 ScramLoginModule (org.apache.kafka.common.security.scram.ScramLoginModule)4 PlainLoginModule (org.apache.kafka.common.security.plain.PlainLoginModule)3 IOException (java.io.IOException)2 ByteBuffer (java.nio.ByteBuffer)2 KafkaException (org.apache.kafka.common.KafkaException)2 ListenerName (org.apache.kafka.common.network.ListenerName)2 NetworkSend (org.apache.kafka.common.network.NetworkSend)2 ApiVersionsRequest (org.apache.kafka.common.requests.ApiVersionsRequest)2 ApiVersionsResponse (org.apache.kafka.common.requests.ApiVersionsResponse)2 TestSecurityConfig (org.apache.kafka.common.security.TestSecurityConfig)2 SelectionKey (java.nio.channels.SelectionKey)1 ArrayList (java.util.ArrayList)1 LinkedHashMap (java.util.LinkedHashMap)1 Random (java.util.Random)1 TopicPartition (org.apache.kafka.common.TopicPartition)1