Package com.mongodb

Interface KmsConnectCallback

Functional Interface:
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

@ThreadSafe @FunctionalInterface public interface KmsConnectCallback
A callback that establishes the connection used for a Key Management Service (KMS) request made by in-use encryption (client-side field level encryption or queryable encryption).

When a callback is configured, the driver invokes it instead of connecting to the KMS host itself, and uses the socket it returns for the KMS request. This enables routing KMS requests through an intermediary, most commonly an HTTP proxy via the HTTP CONNECT method.

The driver always negotiates TLS with the KMS host itself over the returned socket, using the SSLContext configured for the KMS provider. Server Name Indication and certificate hostname verification target the KMS host named by the context, not the address the callback actually connected to. Implementations therefore MUST NOT negotiate TLS with the KMS host themselves; they must return a socket over which a TLS handshake with the KMS host can be performed. An implementation may use TLS for its own connection to an intermediary, in which case it returns an SSLSocket and the driver layers the KMS host's TLS session on top of it.

An IOException thrown by an implementation is treated as a transient network error.

This is applicable only when using the synchronous variant of MongoClient. The reactive streams driver, and the drivers built on it, reject a configured callback rather than connecting to KMS hosts directly.

Authenticating to an intermediary is the responsibility of the implementation. For a proxy requiring HTTP Basic authentication, for example, the implementation adds a Proxy-Authorization header to the CONNECT request.

Example of an implementation that tunnels through an HTTP proxy:


 KmsConnectCallback callback = context -> {
     Socket socket = new Socket();
     try {
         socket.connect(new InetSocketAddress("proxy.example.com", 8080));

         String target = context.getHost() + ":" + context.getPort();
         socket.getOutputStream().write(
                 ("CONNECT " + target + " HTTP/1.1\r\nHost: " + target + "\r\n\r\n").getBytes(StandardCharsets.US_ASCII));

         // Read the status line and confirm a 2xx status, throwing an IOException otherwise. Match the status code
         // rather than the whole status line, as proxies differ in the HTTP version they reply with. Read the
         // response one byte at a time, up to the end of the header block, so that no byte of the TLS handshake that
         // the driver performs over this socket is consumed.
         readAndCheckProxyResponse(socket.getInputStream());
     } catch (IOException | RuntimeException e) {
         // The driver cannot close a socket that was never returned to it.
         socket.close();
         throw e;
     }

     return socket;
 };
 
Since:
5.11
See Also:
  • Method Summary

    Modifier and Type
    Method
    Description
    Returns a socket connected such that a TLS handshake with the KMS host can be performed over it.
  • Method Details

    • connect

      Socket connect(KmsConnectContext context) throws IOException
      Returns a socket connected such that a TLS handshake with the KMS host can be performed over it.

      Ownership of the returned socket passes to the driver, which closes it once the KMS request completes.

      Parameters:
      context - the details of the connection to establish
      Returns:
      a connected socket, which must not have an established TLS session with the KMS host
      Throws:
      IOException - if the connection cannot be established. This is treated as a transient network error.