Hi Pulsar community,

Voting for https://github.com/apache/pulsar/issues/15289

Discussion thread:
https://lists.apache.org/thread/fblmm8oc7h907cfnppvk71o2cbp5mk8q

Thanks,
Zixuan

------

## Motivation

The client supports TLS transport encryption and TLS authentication, this
code so like:

```java
PulsarClient client = PulsarClient.builder()
                .serviceUrl("pulsar+ssl://localhost:6651")
                .tlsTrustCertsFilePath("/path/to/cacert.pem")
                .authentication(AuthenticationTls.class.getName(),
authParams)
                .build()
```

This causes an issue that cannot use other authentication with TLS
transport encryption, and also made our confusion if we use TLS transport
encryption by setting `authentication`.

## Goal

Split client TLS transport encryption from authentication is used to
support TLS transport encryption with any authentication.

## API Changes

- Add new methods in `org.apache.pulsar.client.api.ClientBuilder`

```java
public interface ClientBuilder extends Serializable, Cloneable {
    /**
     * Set the path to the TLS key file.
     *
     * @param tlsKeyFilePath
     * @return the client builder instance
     */
    ClientBuilder tlsKeyFilePath(String tlsKeyFilePath);

    /**
     * Set the path to the TLS certificate file.
     *
     * @param tlsCertificateFilePath
     * @return the client builder instance
     */
    ClientBuilder tlsCertificateFilePath(String tlsCertificateFilePath);

    /**
     * The file format of the key store file.
     *
     * @param tlsKeyStoreType
     * @return the client builder instance
     */
    ClientBuilder tlsKeyStoreType(String tlsKeyStoreType);

    /**
     * The location of the key store file.
     *
     * @param tlsTrustStorePath
     * @return the client builder instance
     */
    ClientBuilder tlsKeyStorePath(String tlsTrustStorePath);

    /**
     * The store password for the key store file.
     *
     * @param tlsKeyStorePassword
     * @return the client builder instance
     */
    ClientBuilder tlsKeyStorePassword(String tlsKeyStorePassword);
}
```

## Implementation

### TLS transport encryption

We can call the `tlsKeyFilePath()`, `tlsCertificateFilePath()` and
`tlsTrustCertsFilePath()` to configurate the TLS transport encryption, the
code so like:

```java
PulsarClient client = PulsarClient.builder()
        .serviceUrl("pulsar+ssl://my-host:6650")
        .tlsTrustCertsFilePath("/path/to/cacert.pem")
        .tlsKeyFilePath("/path/to/client-key.pem")
        .tlsCertificateFilePath("/path/to/client-cert.pem")
        .build();
```


Call the `tlsKeyFilePath()`, `tlsTrustStorePath()` to configurate the JKS
TLS transport encryption, the code so like:

```java
PulsarClient client = PulsarClient.builder()
        .serviceUrl("pulsar+ssl://my-host:6650")
        .tlsKeyFilePath("/path/key.jks")
        .tlsKeyStorePassword("hello")
        .tlsTrustStorePath("/path/trust.jks")
        .tlsTrustStorePassword("hello")
        .build();
```


### TLS transport encryption with any authentication

We can call the `tlsKeyFilePath()`, `tlsCertificateFilePath()`,
`tlsTrustCertsFilePath()` and `authentication()` to configurate  the TLS
transport encryption with any authentication, the code so like:

```java
PulsarClient client = PulsarClient.builder()
        .serviceUrl("pulsar+ssl://my-host:6650")
        .tlsTrustCertsFilePath("/path/to/cacert.pem")
        .tlsKeyFilePath("/path/to/client-key.pem")
        .tlsCertificateFilePath("/path/to/client-cert.pem")
        .authentication(AuthenticationTls.class.getName() /*
AuthenticationToken.class.getName()*/, authParams)
        .builder()
```

Call the `tlsKeyFilePath()`, `tlsTrustStorePath()` to configurate the JKS
TLS transport encryption, the code so like:

```java
PulsarClient client = PulsarClient.builder()
        .serviceUrl("pulsar+ssl://my-host:6650")
        .tlsKeyFilePath("/path/key.jks")
        .tlsKeyStorePassword("hello")
        .tlsTrustStorePath("/path/trust.jks")
        .authentication(AuthenticationTls.class.getName() /*
AuthenticationToken.class.getName()*/, authParams)
        .build();
```

For `AuthenticationTls`, we need to check the authParams, when the
authParams is empty, we need to read TLS config from `ClientBuilder`,
otherwise read from the authParams, the authParams can override the config
from `ClientBuilder`, if still is empty, we read TLS config from
`ClientBuilder`.

### Plan test

- Verify TLS transport encryption without authentication
- Verify TLS transport encryption with token authentication
- Verify TLS transport encryption with TLS authentication
- Verify JKS TLS transport encryption without authentication
- Verify JKS TLS transport encryption with token authentication
- Verify JKS TLS transport encryption with TLS authentication

### Compatibility

None.

Reply via email to