Search in sources :

Example 71 with SecurityProtocol

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

Example 72 with SecurityProtocol

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);
}
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 73 with SecurityProtocol

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;
    }
}
Also used : SecurityProtocol(org.apache.kafka.common.security.auth.SecurityProtocol) AssertionFailedError(org.opentest4j.AssertionFailedError) MockTime(org.apache.kafka.common.utils.MockTime) Test(org.junit.jupiter.api.Test)

Example 74 with SecurityProtocol

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

Example 75 with SecurityProtocol

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");
}
Also used : HashMap(java.util.HashMap) SecurityProtocol(org.apache.kafka.common.security.auth.SecurityProtocol) PlainLoginModule(org.apache.kafka.common.security.plain.PlainLoginModule) Test(org.junit.jupiter.api.Test)

Aggregations

SecurityProtocol (org.apache.kafka.common.security.auth.SecurityProtocol)106 Test (org.junit.jupiter.api.Test)50 Test (org.junit.Test)29 HashMap (java.util.HashMap)22 InetSocketAddress (java.net.InetSocketAddress)14 NetworkSend (org.apache.kafka.common.network.NetworkSend)11 RequestHeader (org.apache.kafka.common.requests.RequestHeader)11 IOException (java.io.IOException)10 PlainLoginModule (org.apache.kafka.common.security.plain.PlainLoginModule)10 TestSecurityConfig (org.apache.kafka.common.security.TestSecurityConfig)9 ScramLoginModule (org.apache.kafka.common.security.scram.ScramLoginModule)9 File (java.io.File)8 ByteBuffer (java.nio.ByteBuffer)8 Properties (java.util.Properties)8 ApiVersionsRequest (org.apache.kafka.common.requests.ApiVersionsRequest)7 ApiVersionsResponse (org.apache.kafka.common.requests.ApiVersionsResponse)7 LogContext (org.apache.kafka.common.utils.LogContext)6 Random (java.util.Random)5 Password (org.apache.kafka.common.config.types.Password)5 ListenerName (org.apache.kafka.common.network.ListenerName)5