...
Note also that ZooKeeper will associate multiple identities with any session that successfully authenticates multiple ways (e.g. both client certificate and SASL). The X.509 identity is the full Distinguished Name from the client's certificate, and this can be changed (i.e. use just a part of the DN) only by implementing and using a custom ZooKeeper authentication provider that overrides the method protected String getClientId(X509Certificate clientCert)
. A client that accesses an ACL-protected Znode is authorized if it has at least 1 of the identities present in any authorizing ACL.
...
There is an additional CLI tool that supports bootstrapping information into ZooKeeper besides ConfigCommand
: kafka-acls.{
bat,sh} (kafka.admin.AclCommand
). Accessing a ZooKeeper instance via this CLI tool will also be required, and passing TLS configuration to it in a secured way will also be necessary.
...
Every config can be prefixed with "authorizer.
" for the case when kafka.security.authorizer.AclAuthorizer
connects via TLS to a ZooKeeper quorum separate from the one that Kafka is using – this specific use case will be identified in the configuration by explicitly setting authorizer.zookeeper.ssl.client.secureenable=true
. In this case the configs prefixed with "authorizer.
" are not "overrides" like the other authorizer ZooKeeper connectivity configs such as connection/session timeouts and max inflight requests; ZooKeeper TLS connectivity values for the authorizer are not "merged" with Kafka's ZooKeeper TLS configs (if any) because semantically the two sets of configs are for different ZooKeeper quorums and there is no guarantee that they would be applicable across the two quorums; any configs that need to be identical across the two ZooKeeper quorums will have to be repeated with and without the prefix. The same defaults described below will apply to the prefixed configs.
Config Key | Documentation |
---|---|
| Set client to use TLS when connecting to ZooKeeper. When true, <code>zookeeper.clientCnxnSocket</code> must be set (typically to <code>org.apache.zookeeper.ClientCnxnSocketNetty</code>); other values to set may include <include list of all other properties below> |
zookeeper.clientCnxnSocket | Typically set to <code>org.apache.zookeeper.ClientCnxnSocketNetty</code> when using TLS connectivity to ZooKeeper |
zookeeper.ssl.keyStorekeystore.location | Keystore location when using a client-side certificate with TLS connectivity to ZooKeeper. Note ZooKeeper's use of camel-case <code>keyStore</code>, which differs from Kafka. |
| Keystore password when using a client-side certificate with TLS connectivity to ZooKeeper. Note ZooKeeper's use of camel-case <code>keyStore</code>, which differs from Kafka. |
zookeeper.ssl.keyStorekeystore.type | Keystore type when using a client-side certificate with TLS connectivity to ZooKeeper. Note ZooKeeper's use of camel-case <code>keyStore</code>, which differs from Kafka. The default value of <code>null</code> means the type will be auto-detected based on the filename extension of the keystore. |
zookeeper.ssl.trustStoretruststore.location | Truststore location when using TLS connectivity to ZooKeeper. Note ZooKeeper's use of camel-case <code>trustStore</code>, which differs from Kafka. |
zookeeper.ssl.trustStoretruststore.password
| Truststore password when using TLS connectivity to ZooKeeper. Note ZooKeeper's use of camel-case <code>trustStore</code>, which differs from Kafka. |
zookeeper.ssl.trustStoretruststore.type | Truststore type when using TLS connectivity to ZooKeeper. Note ZooKeeper's use of camel-case <code>trustStore</code>, which differs from Kafka. The default value of <code>null</code> means the type will be auto-detected based on the filename extension of the truststore. |
| Specifies the protocol to be used in ZooKeeper TLS negotiation |
zookeeper.ssl.enabledProtocolsenabled.protocols | Specifies the enabled protocol(s) in ZooKeeper TLS negotiation (csv). Note ZooKeeper's use of camel-case <code>enabledProtocols</code>, which differs from Kafka. The default value of <code>null</code> means the enabled protocol will be the value of the <code>zookeeper.ssl.protocol</code> configuration property. |
zookeeper.ssl.ciphersuitescipher.suites | Specifies the enabled cipher suites to be used in ZooKeeper TLS negotiation (csv). The default value of <code>null</code> means the list of enabled cipher suites is determined by the Java runtime being used. |
zookeeper.ssl.context.supplier.class | Specifies the class to be used for creating SSL context in ZooKeeper TLS communication |
| Specifies whether to enable hostname verification in the ZooKeeper TLS negotiation process. Disabling it is only recommended for testing purposes. |
| Specifies whether to enable Certificate Revocation List in the ZooKeeper TLS protocols |
| Specifies whether to enable Online Certificate Status Protocol in the ZooKeeper TLS protocols |
...
- New Kafka configurations, both non-prefixed as well as prefixed with "
authorizer.
" - A new --zk-tls-config-file parameter for:
- ZooKeeper Security Migration Tool
- Config Command CLI (for the special use case of bootstrapping TLS-enabled ZooKeeper)
- ACL Command CLIs (for the special use case of bootstrapping TLS-enabled ZooKeeper)
- A new -zk-tls-config-file parameter in the ZooKeeper Shell (again, note the single dash as opposed to the double-dash used above)
ZooKeeper supports Java system properties for configuration, and there are Kafka TLS configuration keys/values that are semantically equivalent to the ZooKeeper configurations in many case as well, so we will define an evaluation algorithm for configuration values as follows:
- System properties define an initial value to be used. For example, if the Java process is started with "
-Dzookeeper.ssl.trustStore.location=/the/path
" then that will be the starting value for thezookeeper.ssl.truststore.location
configuration. Note that the system properties use the ZooKeeper camelcase convention; this cannot be changed. - Explicit configuration values take precedence over any value defined via a system property. So if in addition to the above system property the configuration explicitly includes "
zookeeper.ssl.truststore.location=/another/path
" then that will be the value for thezookeeper.ssl.truststore.location
configuration - If no value exists at this point – no system property and no explicit value – then any explicit, equivalent Kafka configuration will be used. So, for example, if no such system property in (1) or config in (2) existed but the same config file contained "
ssl.truststore.location=/the/kafka/path
" then that would be the value used.
The list of configs for which the above algorithm will be used is as follows:
Zk System Property | "zookeeper." config | Potentially "Inherited" Kafka Config |
---|---|---|
zookeeper.ssl.keyStore.{location, password,type} | zookeeper.ssl.keystore.{location,password,type} | ssl.keystore.{location,passsord,type} |
zookeeper.ssl.trustStore.{location, password,type} | zookeeper.ssl.truststore.{location,password,type} | ssl.truststore.{location,passsord,type} |
zookeeper.ssl.ciphersuites | zookeeper.ssl.cipher.suites | ssl.cipher.suites |
zookeeper.ssl.protocol | zookeeper.ssl.protocol | ssl.protocol |
zookeeper.ssl.enabledProtocols | zookeeper.ssl.enabled.protocols | ssl.enabled.protocols |
Note that inheritance occurs on brokers and on CLI tools.
Note that inheritance of Kafka configs does not occur for AclAuthorizer
on the broker when it is explicitly pointed at a separate ZooKeeper quorum, but system properties will be applied in this case anyway (these cannot be disabled).
The proposed changes also include the addition of:
...
The connection between Kafka and Zookeeper is not on a critical path related to performance – brokers don't repeatedly communicate with Zookeeper as they process messages, for example – so introducing TLS encryption here does not require explicit performance testing.
Rejected Alternatives
Direct ZooKeeper Configs
ZooKeeper uses camelCase configs that are inconsistent with Kafka broker configs:
ZooKeeper Config | Kafka Broker Config |
---|---|
zookeeper.ssl.keyStore.location | ssl.keystore.location |
zookeeper.ssl.keyStore.password | ssl.keystore.password |
zookeeper.ssl.keyStore.type | ssl.keystore.type |
zookeeper.ssl.trustStore.location | ssl.truststore.location |
zookeeper.ssl.trustStore.password | ssl.truststore.password |
zookeeper.ssl.trustStore.type | ssl.truststore.type |
zookeeper.ssl.ciphersuites | ssl.cipher.suites |
zookeeper.ssl.enabledProtocols | ssl.enabled.protocols |
It would be confusing and prone to mistake to have such a mismatch – especially for people who tend to know very little about ZooKeeper compared to Kafka.
The ZooKeeper config "zookeeper.client.secure" is also confusing – it only refers to whether the client should be configured to communicate with a TLS-encrypted ZK socket and has nothing to do with any other security-related client configuration that might be implied by the term "secure" (e.g. SASL, ACLs). We therefore use the broker-side config "zookeeper.ssl.client.enable" instead.N/A