Using TLS with KeyStore configure

概述

Apache Pulsar 支持 TLS 加密 and TLS 身份验证 客户端和 Apache Pulsar 服务之间的TLS 身份验证 默认情况下,它使用 PEM 格式文件配置。 此页面试图使用 KeyStore 类型为 TLS 配置。

使用 KeyStore 配置的 TLS 加密

生成 TLS 密钥和证书

部署TLS的第一步是为集群中的每台机器生成密钥和证书。 您可以使用 Java keytool 工具来完成这项任务。 我们首先将为每台 Broker 生成一个临时的 keystore,以便我们能够使用 CA 导出和进行签名。

  1. keytool-keystore broker.keystore.jks -alias localhost -validity {validity} -genkeypair -keyalg RSA

你必须在上面的命令中指定两个参数:

  1. keystore: 这个 keystore 文件保存了证书信息。 这个* keystore *文件包含了证书的私有秘钥信息;因此,你必须安全的保存它。
  2. validity: 证书的有效时间。

确保通用名称(CN) 与服务器完全合格的域名(FQDN) 完全匹配。 客户端将会把 CN 与 DNS 域名进行比较,以确保它确实连接到所需的服务器,而不是恶意的连接。

创建自定义 CA

在第一步之后,集群中的每个 Broker 将包含一个公私钥对,并且拥有用来识别机器的证书。 然而,证书是没有签名的,这意味着攻击者可以制作这样一份证书,来假装是任何机器。

因此,重要的是要防止伪造证书,为此要在为集群中的每台机器进行签名。 证书颁发机构(CA)负责签发证书。 CA 的工作内容类似签发护照的政府部门,即每本护照都有政府的印章(签名),这使得每本护照难以被伪造。 其他国家的政府通过验证这个印章,确保护照是真实的。 同样,CA 签署证书,并且通过签名加密证书,保证证书在不能被伪造。 因此,只要 CA 是一个可以信任的机构,就能确保客户端能够连上真正的服务器。

  1. openssl req -new -x509 -keyout ca-key -out ca-cert -days 365

CA 生成的是一个简单的公私钥对和证书,并打算签署其他证书。

下一步是将生成的CA 添加到客户端的信任秘钥库,以便客户端能够信任这个CA:

  1. keytool -keystore client.truststore.jks -alias CARoot -import -file ca-cert

注意:你可以通过在 Broker 上配置lsRequireTrustedClientCertOnConnecttrue来配置客户端需要经过认证才能访问。那么你必须总是为每个 Broker 提供一个可信任的库,并且它拥有所有用来给客户端秘钥签名的 CA 证书。

  1. keytool -keystore broker.truststore.jks -alias CARoot -import -file ca-cert

与存储每个机器自身身份的密钥库形成对比, 客户端信任的秘钥库是存储客户端应信任的所有证书 。 将证书导入一个可信赖库,意味着信任由该证书签名的所有证书。 从上述类推,信任政府(CA)也意味着信任所有已被发布的护照(证书) 此属性称为信任链,在大型BookKeeper集群上部署TLS时特别有用。 您可以使用单个CA对群集中的所有证书进行签名,并让所有计算机共享信任该CA相同的信任库。 这样,所有机器都可以对所有其他机器进行身份验证。

签署证书

下一步是使用我们生成的CA对密钥库中的所有证书进行签名。 首先,您需要从密钥库导出证书:

  1. keytool -keystore broker.keystore.jks -alias localhost -certreq -file cert-file

然后用CA签署:

  1. openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days {validity} -CAcreateserial -passin pass:{ca-password}

最后,您需要将CA的证书和签名证书导入密钥库:

  1. keytool -keystore broker.keystore.jks -alias CARoot -import -file ca-cert
  2. keytool -keystore broker.keystore.jks -alias localhost -import -file cert-signed

参数的定义如下所示:

  1. keystore: 密钥库的位置
  2. ca-cert:CA 的证书
  3. ca-key:CA 的私钥
  4. ca-password:CA 的密码
  5. cert-file:broker 导出的、未签名的证书
  6. cert-signed:broker 的签名证书

配置代理

Brokers 通过提供有效的 brokerServicePortTlswebServicePortTls 来启用 TLS,并且还需要将 tlsEnabledWithKeyStore 设置为 true 以使用 KeyStore 类型配置. 除此之外,还需要提供 KeyStore 路径、KeyStore 密码、TrustStore 路径和 TrustStore 密码。 并且由于broker会创建内部client/admin客户端来与其他broker进行通信,用户还需要为他们提供配置,这类似于用户如何配置外部client/admin-client。 如果 tlsRequireTrustedClientCertOnConnecttrue,如果客户端证书不受信任,代理将拒绝连接。

代理端需要以下 TLS 配置:

  1. tlsEnabledWithKeyStore=true
  2. # 密钥存储
  3. tlsKeyStoreType=JKS
  4. tlsKeyStore=/var/private/tls/broker.keystore.jks
  5. tlsKeyStorePassword=brokerpw
  6. # 信任存储
  7. tlsTrustStoreType=JKS
  8. tlsTrustStore=/var/private/tls/broker.truststore.jks
  9. tlsTrustStorePassword=brokerpw
  10. # 内部客户端/管理员客户端配置
  11. brokerClientTlsEnabled=true
  12. brokerClientTlsEnabledWithKeyStore=true
  13. brokerClientTlsTrustStoreType=JKS
  14. brokerClientTlsTrustStore=/var/private/tls/client.truststore.jks
  15. brokerClientTlsTrustStorePassword=clientpw
  16. 文本
  17. XPath: /pre[8]/code

注意:必须通过文件系统权限限制对存储文件的访问。

如果您在经纪上配置了TLS,要禁用非TLS端口,您可以将以下配置的值设置为空。

  1. brokerServicePort=
  2. webServicePort=

在这种情况下,您需要进行以下配置。

  1. brokerClientTlsEnabled=true // Set this to true
  2. brokerClientTlsEnabledWithKeyStore=true // Set this to true
  3. brokerClientTlsTrustStore= // Set this to your desired value
  4. brokerClientTlsTrustStorePassword= // Set this to your desired value

Optional settings that may worth consider:

  1. tlsClientAuthentication=false: Enable/Disable using TLS for authentication. This config when enabled will authenticate the other end of the communication channel. It should be enabled on both brokers and clients for mutual TLS.
  2. tlsCiphers=[TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256], A cipher suite is a named combination of authentication, encryption, MAC and key exchange algorithm used to negotiate the security settings for a network connection using TLS network protocol. By default, it is null. OpenSSL Ciphers JDK Ciphers
  3. tlsProtocols=[TLSv1.3,TLSv1.2] (list out the TLS protocols that you are going to accept from clients). By default, it is not set.

Configuring Clients

This is similar to [TLS encryption configuing for client with PEM type](/docs/zh-CN/2.8.2/security-tls-transport#Client configuration). For a a minimal configuration, user need to provide the TrustStore information.

例如:

  1. 对于命令行工具,例如pulsar-adminpulsar-perf 和 [pulsar-client](reference-cli-tools#pulsar- client) 在 Pulsar 安装中使用 conf/client.conf 配置文件。

    1. webServiceUrl=https://broker.example.com:8443/
    2. brokerServiceUrl=pulsar+ssl://broker.example.com:6651/
    3. useKeyStoreTls=true
    4. tlsTrustStoreType=JKS
    5. tlsTrustStorePath=/var/private/tls/client.truststore.jks
    6. tlsTrustStorePassword=clientpw
  2. 用于 Java 客户端

    1. import org.apache.pulsar.client.api.PulsarClient;
    2. PulsarClient client = PulsarClient.builder()
    3. .serviceUrl("pulsar+ssl://broker.example.com:6651/")
    4. .enableTls(true)
    5. .useKeyStoreTls(true)
    6. .tlsTrustStorePath("/var/private/tls/client.truststore.jks")
    7. .tlsTrustStorePassword("clientpw")
    8. .allowTlsInsecureConnection(false)
    9. .build();
  3. for java admin client

  1. PulsarAdmin amdin = PulsarAdmin.builder().serviceHttpUrl("https://broker.example.com:8443")
  2. .useKeyStoreTls(true)
  3. .tlsTrustStorePath("/var/private/tls/client.truststore.jks")
  4. .tlsTrustStorePassword("clientpw")
  5. .allowTlsInsecureConnection(false)
  6. .build();

使用 KeyStore 配置的 TLS 身份验证

This similar to TLS authentication with PEM type

broker authentication config

broker.conf

  1. # Configuration to enable authentication
  2. authenticationEnabled=true
  3. authenticationProviders=org.apache.pulsar.broker.authentication.AuthenticationProviderTls
  4. # this should be the CN for one of client keystore.
  5. superUserRoles=admin
  6. # Enable KeyStore type
  7. tlsEnabledWithKeyStore=true
  8. requireTrustedClientCertOnConnect=true
  9. # key store
  10. tlsKeyStoreType=JKS
  11. tlsKeyStore=/var/private/tls/broker.keystore.jks
  12. tlsKeyStorePassword=brokerpw
  13. # trust store
  14. tlsTrustStoreType=JKS
  15. tlsTrustStore=/var/private/tls/broker.truststore.jks
  16. tlsTrustStorePassword=brokerpw
  17. # internal client/admin-client config
  18. brokerClientTlsEnabled=true
  19. brokerClientTlsEnabledWithKeyStore=true
  20. brokerClientTlsTrustStoreType=JKS
  21. brokerClientTlsTrustStore=/var/private/tls/client.truststore.jks
  22. brokerClientTlsTrustStorePassword=clientpw
  23. # internal auth config
  24. brokerClientAuthenticationPlugin=org.apache.pulsar.client.impl.auth.AuthenticationKeyStoreTls
  25. brokerClientAuthenticationParameters={"keyStoreType":"JKS","keyStorePath":"/var/private/tls/client.keystore.jks","keyStorePassword":"clientpw"}
  26. # currently websocket not support keystore type
  27. webSocketServiceEnabled=false

client authentication configuring

Besides the TLS encryption configuring. The main work is configuring the KeyStore, which contains a valid CN as client role, for client.

例如:

  1. 对于命令行工具,例如pulsar-adminpulsar-perf 和 [pulsar-client](reference-cli-tools#pulsar- client) 在 Pulsar 安装中使用 conf/client.conf 配置文件。

    1. webServiceUrl=https://broker.example.com:8443/
    2. brokerServiceUrl=pulsar+ssl://broker.example.com:6651/
    3. useKeyStoreTls=true
    4. tlsTrustStoreType=JKS
    5. tlsTrustStorePath=/var/private/tls/client.truststore.jks
    6. tlsTrustStorePassword=clientpw
    7. authPlugin=org.apache.pulsar.client.impl.auth.AuthenticationKeyStoreTls
    8. authParams={"keyStoreType":"JKS","keyStorePath":"/path/to/keystorefile","keyStorePassword":"keystorepw"}
  2. 用于 Java 客户端

    1. import org.apache.pulsar.client.api.PulsarClient;
    2. PulsarClient client = PulsarClient.builder()
    3. .serviceUrl("pulsar+ssl://broker.example.com:6651/")
    4. .enableTls(true)
    5. .useKeyStoreTls(true)
    6. .tlsTrustStorePath("/var/private/tls/client.truststore.jks")
    7. .tlsTrustStorePassword("clientpw")
    8. .allowTlsInsecureConnection(false)
    9. .authentication(
    10. "org.apache.pulsar.client.impl.auth.AuthenticationKeyStoreTls",
    11. "keyStoreType:JKS,keyStorePath:/var/private/tls/client.keystore.jks,keyStorePassword:clientpw")
    12. .build();
  3. for java admin client

    1. PulsarAdmin amdin = PulsarAdmin.builder().serviceHttpUrl("https://broker.example.com:8443")
    2. .useKeyStoreTls(true)
    3. .tlsTrustStorePath("/var/private/tls/client.truststore.jks")
    4. .tlsTrustStorePassword("clientpw")
    5. .allowTlsInsecureConnection(false)
    6. .authentication(
    7. "org.apache.pulsar.client.impl.auth.AuthenticationKeyStoreTls",
    8. "keyStoreType:JKS,keyStorePath:/var/private/tls/client.keystore.jks,keyStorePassword:clientpw")
    9. .build();

启用 TLS 日志

You can enable TLS debug logging at the JVM level by starting the brokers and/or clients with javax.net.debug system property. 例如:

  1. -Djavax.net.debug=all

You can find more details on this in Oracle documentation on debugging SSL/TLS connections.