@Override public ApiVersionsRequest build(short version) { return new ApiVersionsRequest(version); }
private void handleApiVersionsRequest(RequestContext context, ApiVersionsRequest apiVersionsRequest) throws IOException { if (saslState != SaslState.HANDSHAKE_OR_VERSIONS_REQUEST) throw new IllegalStateException("Unexpected ApiVersions request received during SASL authentication state " + saslState); if (apiVersionsRequest.hasUnsupportedRequestVersion()) sendKafkaResponse(context, apiVersionsRequest.getErrorResponse(0, Errors.UNSUPPORTED_VERSION.exception())); else { sendKafkaResponse(context, apiVersionsResponse()); setSaslState(SaslState.HANDSHAKE_REQUEST); } }
@Override protected Struct toStruct() { return new Struct(ApiKeys.API_VERSIONS.requestSchema(version())); }
case SEND_APIVERSIONS_REQUEST: ApiVersionsRequest apiVersionsRequest = new ApiVersionsRequest((short) 0); send(apiVersionsRequest.toSend(node, nextRequestHeader(ApiKeys.API_VERSIONS, apiVersionsRequest.version()))); setSaslState(SaslState.RECEIVE_APIVERSIONS_RESPONSE); break;
/** * Tests that ApiVersionsRequest after Kafka SASL handshake request flow, * but prior to actual SASL authentication, results in authentication failure. * This is similar to {@link #testUnauthenticatedApiVersionsRequest(SecurityProtocol, short)} * where a non-SASL client is used to send requests that are processed by * {@link SaslServerAuthenticator} of the server prior to client authentication. */ @Test public void testInvalidApiVersionsRequestSequence() throws Exception { SecurityProtocol securityProtocol = SecurityProtocol.SASL_PLAINTEXT; configureMechanisms("PLAIN", Arrays.asList("PLAIN")); server = createEchoServer(securityProtocol); // Send handshake request followed by ApiVersionsRequest String node1 = "invalid1"; createClientConnection(SecurityProtocol.PLAINTEXT, node1); sendHandshakeRequestReceiveResponse(node1, (short) 1); ApiVersionsRequest request = createApiVersionsRequestV0(); RequestHeader versionsHeader = new RequestHeader(ApiKeys.API_VERSIONS, request.version(), "someclient", 2); selector.send(request.toSend(node1, versionsHeader)); NetworkTestUtils.waitForChannelClose(selector, node1, ChannelState.READY.state()); selector.close(); // Test good connection still works createAndCheckClientConnection(securityProtocol, "good1"); }
assertTrue(requestAndSize.request instanceof ApiVersionsRequest); ApiVersionsRequest request = (ApiVersionsRequest) requestAndSize.request; assertTrue(request.hasUnsupportedRequestVersion());
/** * Tests that unsupported version of ApiVersionsRequest before SASL handshake request * returns error response and does not result in authentication failure. This test * is similar to {@link #testUnauthenticatedApiVersionsRequest(SecurityProtocol, short)} * where a non-SASL client is used to send requests that are processed by * {@link SaslServerAuthenticator} of the server prior to client authentication. */ @Test public void testApiVersionsRequestWithUnsupportedVersion() throws Exception { short handshakeVersion = ApiKeys.SASL_HANDSHAKE.latestVersion(); SecurityProtocol securityProtocol = SecurityProtocol.SASL_PLAINTEXT; configureMechanisms("PLAIN", Arrays.asList("PLAIN")); server = createEchoServer(securityProtocol); // Send ApiVersionsRequest with unsupported version and validate error response. String node = "1"; createClientConnection(SecurityProtocol.PLAINTEXT, node); RequestHeader header = new RequestHeader(ApiKeys.API_VERSIONS, Short.MAX_VALUE, "someclient", 1); ApiVersionsRequest request = new ApiVersionsRequest.Builder().build(); selector.send(request.toSend(node, header)); ByteBuffer responseBuffer = waitForResponse(); ResponseHeader.parse(responseBuffer); ApiVersionsResponse response = ApiVersionsResponse.parse(responseBuffer, (short) 0); assertEquals(Errors.UNSUPPORTED_VERSION, response.error()); // Send ApiVersionsRequest with a supported version. This should succeed. sendVersionRequestReceiveResponse(node); // Test that client can authenticate successfully sendHandshakeRequestReceiveResponse(node, handshakeVersion); authenticateUsingSaslPlainAndCheckConnection(node, handshakeVersion > 0); }
public static ApiVersionsRequest parse(ByteBuffer buffer, short version) { return new ApiVersionsRequest(ApiKeys.API_VERSIONS.parseRequest(version, buffer), version); }
@Override public ApiVersionsResponse getErrorResponse(int throttleTimeMs, Throwable e) { short version = version(); switch (version) { case 0: return new ApiVersionsResponse(Errors.forException(e), Collections.emptyList()); case 1: case 2: return new ApiVersionsResponse(throttleTimeMs, Errors.forException(e), Collections.emptyList()); default: throw new IllegalArgumentException(String.format("Version %d is not valid. Valid versions for %s are 0 to %d", version, this.getClass().getSimpleName(), ApiKeys.API_VERSIONS.latestVersion())); } }
public RequestAndSize parseRequest(ByteBuffer buffer) { if (isUnsupportedApiVersionsRequest()) { // Unsupported ApiVersion requests are treated as v0 requests and are not parsed ApiVersionsRequest apiVersionsRequest = new ApiVersionsRequest((short) 0, header.apiVersion()); return new RequestAndSize(apiVersionsRequest, 0); } else { ApiKeys apiKey = header.apiKey(); try { short apiVersion = header.apiVersion(); Struct struct = apiKey.parseRequest(apiVersion, buffer); AbstractRequest body = AbstractRequest.parseRequest(apiKey, apiVersion, struct); return new RequestAndSize(body, struct.sizeOf()); } catch (Throwable ex) { throw new InvalidRequestException("Error getting request for apiKey: " + apiKey + ", apiVersion: " + header.apiVersion() + ", connectionId: " + connectionId + ", listenerName: " + listenerName + ", principal: " + principal, ex); } } }
return new SaslHandshakeRequest(struct, apiVersion); case API_VERSIONS: return new ApiVersionsRequest(struct, apiVersion); case CREATE_TOPICS: return new CreateTopicsRequest(struct, apiVersion);
Request(ChannelHandlerContext ctx, ByteBuffer buffer) { this.requestId = buffer.getShort(); buffer.rewind(); header = RequestHeader.parse(buffer); if (header.apiKey() == ApiKeys.API_VERSIONS.id && !Protocol.apiVersionSupported(header.apiKey(), header.apiVersion())) { body = new ApiVersionsRequest(); } else { body = AbstractRequest.getRequest(header.apiKey(), header.apiVersion(), buffer); } this.clientAddress = ((InetSocketAddress) ctx.getChannel().getRemoteAddress()).getAddress(); }