TLS 암호화
TLS 암호화 (TLS Encryption)
전송 계층 보안(TLS)을 사용해 Pulsar 브로커와 클라이언트 사이의 트래픽을 암호화하는 방법을 설명해요. 기본값은 평문 통신이므로, 민감한 데이터를 다룰 때는 이 설정을 꼭 챙겨야 해요.
출처: 문서
본문
TLS 개요 (TLS overview)
전송 계층 보안(TLS)은 공개 키 암호화(public key cryptography)의 한 형태예요. 기본적으로 Pulsar 클라이언트는 Pulsar 서비스와 평문으로 통신해요. 즉 모든 데이터가 평문으로 전송된다는 뜻이에요. TLS로 이 트래픽을 암호화하면 중간자(man-in-the-middle) 공격자의 도청으로부터 트래픽을 보호할 수 있어요.
이 섹션은 Pulsar에서 TLS 암호화를 구성하는 방법을 소개해요. Pulsar에서 mTLS 인증을 구성하는 방법은 mTLS 인증 문서를 참고해요. 또는 TLS 전송 암호화 위에 또 다른 Athenz 인증을 사용할 수도 있어요.
note TLS 암호화를 활성화하면 암호화 오버헤드로 인해 성능에 영향을 줄 수 있어요.
TLS 인증서 (TLS certificates)
TLS 인증서에는 다음 세 가지 유형이 있어요. 각 인증서(키 쌍)는 메시지를 암호화하는 공개 키와 메시지를 복호화하는 개인 키를 모두 포함해요.
- 인증 기관(Certificate Authority, CA)
- CA 개인 키는 관련된 모든 당사자에게 배포돼요.
- CA 공개 키(신뢰 인증서(trust cert))는 브로커나 클라이언트의 인증서에 서명하는 데 사용돼요.
- 서버 키 쌍
- 클라이언트 키 쌍(상호 TLS용)
서버·클라이언트 인증서 모두 먼저 인증서 요청과 함께 개인 키가 생성되고, 신뢰 인증서가 인증서 요청에 서명한 뒤 공개 키(인증서)가 생성돼요. mTLS 인증이 활성화되면 서버는 신뢰 인증서를 사용해 클라이언트가 인증 기관이 서명한 키 쌍을 가졌는지 검증해요. 클라이언트 인증서의 CN(Common Name)은 클라이언트의 역할 토큰으로 사용되고, 서버 인증서의 SAN(Subject Alternative Name)은 호스트 이름 검증에 사용돼요.
note 이 인증서들의 유효 기간은 365일이에요. 서명 알고리즘은
sha256또는sha512를 사용할 것을 강력히 권장하며sha1은 지원되지 않아요.
인증서 형식 (Certificate formats)
TLS 암호화를 구성할 때 다음 인증서 형식 중 하나를 사용할 수 있어요.
- 권장: PEM(Privacy Enhanced Mail). 자세한 지침은 PEM으로 TLS 암호화 구성을 참고해요.
- 선택: Java KeyStore(JKS). 자세한 지침은 KeyStore로 TLS 암호화 구성을 참고해요.
호스트 이름 검증 (Hostname verification)
호스트 이름 검증은 TLS 보안 기능으로, 클라이언트가 연결하는 호스트 이름과 서버 인증서의 SAN(Subject Alternative Name)이 일치하지 않으면 클라이언트가 서버에 연결을 거부하는 기능이에요. 공격자가 신뢰하는 CA가 서명한 인증서를 보유한 경우에도 중간자 공격을 방어해요.
Pulsar 5.0부터 호스트 이름 검증은 기본적으로 활성화돼요. Pulsar 클라이언트와, 다른 브로커의 클라이언트 역할을 하는 브로커/프록시/지역 복제 연결 모두에 해당해요. 따라서 모든 서버 인증서는 클라이언트가 서버에 도달할 때 사용하는 호스트 이름과 일치하는 SAN을 가져야 해요(각 브로커/프록시는 DNS 레코드와 일치하는 SAN이 있는 인증서가 필요해요. *.broker.example.com 같은 와일드카드 SAN은 호스트 그룹을 커버할 수 있어요).
호스트 이름 매칭에는 SAN만 사용돼요. 인증서의 CN(Common Name) 매칭은 RFC 6125에서 폐기됐고 Pulsar 5.0에서 제거됐어요. CN에만 호스트 이름을 담고(일치하는 SAN이 없는) 인증서는 거부돼요. 적절한 SAN으로 다시 생성해야 해요(서버 인증서 생성 참고). 클라이언트 인증서의 CN은 여전히 mTLS 인증에서 클라이언트의 역할 토큰으로 사용돼요. 이 변경은 서버 호스트 이름 매칭에만 영향을 미쳐요.
호스트 이름 검증이 성공하려면 SAN이 클라이언트가 연결하는 FQDN(정규화된 도메인 이름)과 정확히 일치해야 해요. enableTlsHostnameVerification을 false로 설정해 끌 수 있어요(프로덕션에서는 권장하지 않아요). 자세한 내용은 클라이언트 구성을 참고해요.
또한 관리자가 CA를 완전히 통제하므로 악의적인 행위자가 중간자 공격을 성공시키기는 어려워요. allowInsecureConnection은 승인된 CA가 서명하지 않은 인증서를 가진 서버에 클라이언트가 연결할 수 있게 해요. 클라이언트는 기본적으로 allowInsecureConnection을 비활성화하며 프로덕션 환경에서는 항상 비활성화해야 해요. allowInsecureConnection을 비활성화하는 한, 중간자 공격은 공격자가 CA에 접근 권한이 있을 때만 가능해요.
PEM으로 mTLS 암호화 구성 (Configure mTLS encryption with PEM)
기본적으로 Pulsar는 netty-tcnative을 사용해요. OpenSSL(기본)과 JDK 두 구현을 포함해요. OpenSSL을 사용할 수 없으면 JDK가 사용돼요.
PEM으로 mTLS 암호화를 구성하려면 다음 단계를 완료해요.
1단계: TLS 인증서 생성 (Step 1: Create TLS certificates)
TLS 인증서 생성은 인증 기관, 서버 인증서, 클라이언트 인증서 생성을 포함해요.
인증 기관 만들기 (Create a certificate authority)
인증 기관(CA)을 사용해 서버·클라이언트 인증서에 모두 서명할 수 있어요. 이렇게 하면 각 당사자가 서로를 신뢰해요. CA는 매우 안전한 위치(이상적으로는 네트워크에서 완전히 분리된 air-gapped, 완전히 암호화된 위치)에 저장해요.
CA를 만들려면 다음 명령을 사용해요.
openssl genrsa -out ca.key.pem 2048
openssl req -x509 -new -nodes -key ca.key.pem -subj "/CN=CARoot" -days 365 -out ca.cert.pem
note macOS의 기본
openssl은 위 명령에서 동작하지 않아요. Homebrew로openssl을 업그레이드해야 해요.
brew install openssl
export PATH="/usr/local/Cellar/openssl@3/3.0.1/bin:$PATH"
brew install 명령 출력의 실제 경로를 사용해요. 버전 번호 3.0.1은 바뀔 수 있다는 점에 주의해요.
서버 인증서 만들기 (Create a server certificate)
CA를 만든 뒤에는 인증서 요청을 만들고 CA로 서명할 수 있어요.
- 서버의 개인 키를 생성해요.
openssl genrsa -out server.key.pem 2048
서버는 키가 PKCS 8 형식일 것을 기대해요. 변환하려면 다음 명령을 입력해요.
openssl pkcs8 -topk8 -inform PEM -outform PEM -in server.key.pem -out server.key-pk8.pem -nocrypt
- 다음 내용으로
server.conf파일을 만들어요.
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=critical, digitalSignature, keyEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
[ dn ]
CN = server
[ alt_names ]
DNS.1 = pulsar
DNS.2 = pulsar.default
IP.1 = 127.0.0.1
IP.2 = 192.168.1.2
tip 호스트 이름 검증을 구성하려면 SAN(Subject Alternative Name)으로
alt_names에 서버의 호스트 이름을 입력해야 해요. 여러 머신이 같은 인증서를 재사용할 수 있도록 와일드카드로 서버 호스트 이름 그룹을 매칭할 수도 있어요. 예:*.server.usw.example.com.
- 인증서 요청을 생성해요.
openssl req -new -config server.conf -key server.key.pem -out server.csr.pem -sha256
- CA로 인증서에 서명해요.
openssl x509 -req -in server.csr.pem -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out server.cert.pem -days 365 -extensions v3_ext -extfile server.conf -sha256
이 시점에서 server.cert.pem 인증서와 server.key-pk8.pem 키가 생겼어요. ca.cert.pem과 함께 브로커와 프록시의 TLS 암호화를 구성하는 데 사용할 수 있어요.
브로커 클라이언트 인증서 만들기 (Create a broker client certificate)
- broker_client의 개인 키를 생성해요.
openssl genrsa -out broker_client.key.pem 2048
broker_client는 키가 PKCS 8 형식일 것을 기대해요. 변환하려면 다음 명령을 입력해요.
openssl pkcs8 -topk8 -inform PEM -outform PEM -in broker_client.key.pem -out broker_client.key-pk8.pem -nocrypt
- 인증서 요청을 생성해요.
CN값은 브로커 클라이언트의 역할 토큰으로 사용된다는 점에 주의해요.
openssl req -new -subj "/CN=broker_client" -key broker_client.key.pem -out broker_client.csr.pem -sha256
- CA로 인증서에 서명해요.
openssl x509 -req -in broker_client.csr.pem -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out broker_client.cert.pem -days 365 -sha256
이 시점에서 broker_client.cert.pem 인증서와 broker_client.key-pk8.pem 키가 생겼어요. ca.cert.pem과 함께 브로커 클라이언트의 TLS 암호화를 구성하는 데 사용할 수 있어요.
admin 인증서 만들기 (Create a admin certificate)
- admin의 개인 키를 생성해요.
openssl genrsa -out admin.key.pem 2048
admin은 키가 PKCS 8 형식일 것을 기대해요. 변환하려면 다음 명령을 입력해요.
openssl pkcs8 -topk8 -inform PEM -outform PEM -in admin.key.pem -out admin.key-pk8.pem -nocrypt
- 인증서 요청을 생성해요.
CN값은 admin의 역할 토큰으로 사용된다는 점에 주의해요.
openssl req -new -subj "/CN=admin" -key admin.key.pem -out admin.csr.pem -sha256
- CA로 인증서에 서명해요.
openssl x509 -req -in admin.csr.pem -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out admin.cert.pem -days 365 -sha256
이 시점에서 admin.cert.pem 인증서와 admin.key-pk8.pem 키가 생겼어요. ca.cert.pem과 함께 pulsar admin의 TLS 암호화를 구성하는 데 사용할 수 있어요.
클라이언트 인증서 만들기 (Create a client certificate)
- 클라이언트의 개인 키를 생성해요.
openssl genrsa -out client.key.pem 2048
클라이언트는 키가 PKCS 8 형식일 것을 기대해요. 변환하려면 다음 명령을 입력해요.
openssl pkcs8 -topk8 -inform PEM -outform PEM -in client.key.pem -out client.key-pk8.pem -nocrypt
- 인증서 요청을 생성해요.
CN값은 클라이언트의 역할 토큰으로 사용된다는 점에 주의해요.
openssl req -new -subj "/CN=client" -key client.key.pem -out client.csr.pem -sha256
- CA로 인증서에 서명해요.
openssl x509 -req -in client.csr.pem -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out client.cert.pem -days 365 -sha256
이 시점에서 client.cert.pem 인증서와 client.key-pk8.pem 키가 생겼어요. ca.cert.pem과 함께 클라이언트의 TLS 암호화를 구성하는 데 사용할 수 있어요.
프록시 인증서 만들기(선택) (Create a proxy certificate (Optional))
- 프록시의 개인 키를 생성해요.
openssl genrsa -out proxy.key.pem 2048
프록시는 키가 PKCS 8 형식일 것을 기대해요. 변환하려면 다음 명령을 입력해요.
openssl pkcs8 -topk8 -inform PEM -outform PEM -in proxy.key.pem -out proxy.key-pk8.pem -nocrypt
- 인증서 요청을 생성해요.
CN값은 프록시의 역할 토큰으로 사용된다는 점에 주의해요.
openssl req -new -subj "/CN=proxy" -key proxy.key.pem -out proxy.csr.pem -sha256
- CA로 인증서에 서명해요.
openssl x509 -req -in proxy.csr.pem -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out proxy.cert.pem -days 365 -sha256
이 시점에서 proxy.cert.pem 인증서와 proxy.key-pk8.pem 키가 생겼어요. ca.cert.pem과 함께 프록시의 TLS 암호화를 구성하는 데 사용할 수 있어요.
2단계: 브로커 구성 (Step 2: Configure brokers)
Pulsar 브로커가 TLS 암호화를 사용하도록 구성하려면 Pulsar 설치의 conf 디렉터리에 있는 broker.conf에 이 설정들을 추가해야 해요. 필요한 곳에 적절한 인증서 경로를 치환해요.
# configure TLS ports
brokerServicePortTls=6651
webServicePortTls=8081
# configure CA certificate
tlsTrustCertsFilePath=/path/to/ca.cert.pem
# configure server certificate
tlsCertificateFilePath=/path/to/server.cert.pem
# configure server's priviate key
tlsKeyFilePath=/path/to/server.key-pk8.pem
# enable mTLS
tlsRequireTrustedClientCertOnConnect=true
# configure mTLS for the internal client
brokerClientTlsEnabled=true
brokerClientTrustCertsFilePath=/path/to/ca.cert.pem
brokerClientCertificateFilePath=/path/to/broker_client.cert.pem
brokerClientKeyFilePath=/path/to/broker_client.key-pk8.pem
TLS 프로토콜 버전과 Cipher 구성 (Configure TLS Protocol Version and Cipher)
브로커(및 프록시)가 TLS 협상에서 특정 TLS 프로토콜 버전과 cipher를 요구하도록 구성하려면 TLS 프로토콜 버전과 cipher를 사용해 클라이언트가 약점이 있을 수 있는 다운그레이드된 TLS 프로토콜 버전이나 cipher를 요청하는 것을 막을 수 있어요.
기본적으로 Pulsar는 OpenSSL을 사용할 수 있으면 사용하고, 아니면 JDK 구현으로 대체해요. OpenSSL은 현재 TLSv1.1, TLSv1.2, TLSv1.3을 지원해요. 지원되는 cipher 목록은 OpenSSL ciphers 명령으로 얻을 수 있어요. 즉 openssl ciphers -tls1_3.
TLS 프로토콜 버전과 cipher 속성 모두 여러 값을 쉼표로 구분해 가질 수 있어요. 프로토콜 버전과 cipher의 가능한 값은 사용 중인 TLS 제공자에 따라 달라져요.
tlsProtocols=TLSv1.3,TLSv1.2
tlsCiphers=TLS_DH_RSA_WITH_AES_256_GCM_SHA384,TLS_DH_RSA_WITH_AES_256_CBC_SHA
tlsProtocols=TLSv1.3,TLSv1.2: 클라이언트로부터 수락할 TLS 프로토콜을 나열해요. 기본값은 설정되지 않아요.tlsCiphers=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: cipher 스위트는 TLS 네트워크 프로토콜을 사용하는 네트워크 연결의 보안 설정을 협상하는 데 사용되는 인증, 암호화, MAC, 키 교환 알고리즘의 명명된 조합이에요. 기본값은 null이에요. 자세한 내용은 OpenSSL Ciphers와 JDK Ciphers를 참고해요.
JDK 11의 경우 문서에서 지원되는 값 목록을 얻을 수 있어요.
3단계: 프록시 구성 (Step 3: Configure proxies)
프록시에서 mTLS 구성은 클라이언트→프록시, 프록시→브로커 두 방향의 연결을 포함해요.
# configure TLS ports
servicePortTls=6651
webServicePortTls=8081
# configure certificates for clients to connect proxy
tlsCertificateFilePath=/path/to/server.cert.pem
tlsKeyFilePath=/path/to/server.key-pk8.pem
tlsTrustCertsFilePath=/path/to/ca.cert.pem
# enable mTLS
tlsRequireTrustedClientCertOnConnect=true
# configure TLS for proxy to connect brokers
tlsEnabledWithBroker=true
brokerClientTrustCertsFilePath=/path/to/ca.cert.pem
brokerClientCertificateFilePath=/path/to/proxy.cert.pem
brokerClientKeyFilePath=/path/to/proxy.key-pk8.pem
4단계: 클라이언트 구성 (Step 4: Configure clients)
TLS 암호화를 활성화하려면 클라이언트가 웹 서비스 URL에는 https://와 포트 8443을, 브로커 서비스 URL에는 pulsar+ssl://와 포트 6651을 사용하도록 구성해야 해요.
위에서 생성한 서버 인증서가 기본 신뢰 체인에 속하지 않으므로, 신뢰 인증서의 경로를 지정하거나(권장) 클라이언트가 신뢰하지 않는 서버 인증서를 허용하도록 활성화해야 해요.
다음 예제는 Java/Python/C++/Node.js/C#/WebSocket 클라이언트의 TLS 암호화를 구성하는 방법을 보여줘요.
- Java
- Python
- C++
- Node.js
- C#
- WebSocket API
Java:
import org.apache.pulsar.client.api.PulsarClient;
PulsarClient client = PulsarClient.builder()
.serviceUrl("pulsar+ssl://broker.example.com:6651/")
.tlsKeyFilePath("/path/to/client.key-pk8.pem")
.tlsCertificateFilePath("/path/to/client.cert.pem")
.tlsTrustCertsFilePath("/path/to/ca.cert.pem")
.enableTlsHostnameVerification(true) // enabled by default since 5.0
.allowTlsInsecureConnection(false) // false by default, in any case
.build();
Python:
from pulsar import Client
client = Client("pulsar+ssl://broker.example.com:6651/",
tls_hostname_verification=True, # enabled by default since 5.0
tls_trust_certs_file_path="/path/to/ca.cert.pem",
tls_allow_insecure_connection=False) // defaults to false from v2.2.0 onwards
C++:
#include <pulsar/Client.h>
ClientConfiguration config = ClientConfiguration();
config.setUseTls(true); // shouldn't be needed soon
config.setTlsTrustCertsFilePath(caPath);
config.setTlsAllowInsecureConnection(false);
config.setAuth(pulsar::AuthTls::create(clientPublicKeyPath, clientPrivateKeyPath));
config.setValidateHostName(true); // enabled by default since 5.0
Node.js:
const Pulsar = require('pulsar-client');
(async () => {
const client = new Pulsar.Client({
serviceUrl: 'pulsar+ssl://broker.example.com:6651/',
tlsTrustCertsFilePath: '/path/to/ca.cert.pem',
useTls: true,
tlsValidateHostname: true, // enabled by default since 5.0
tlsAllowInsecureConnection: false,
});
})();
C#:
var certificate = new X509Certificate2("ca.cert.pem");
var client = PulsarClient.Builder()
.TrustedCertificateAuthority(certificate) //If the CA is not trusted on the host, you can add it explicitly.
.VerifyCertificateAuthority(true) //Default is 'true'
.VerifyCertificateName(false) //Default is 'false'
.Build();
note
VerifyCertificateName은 C# 클라이언트의 호스트 이름 검증 구성을 가리켜요.
WebSocket API:
import websockets
import asyncio
import base64
import json
import ssl
import pathlib
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
client_cert_pem = pathlib.Path(__file__).with_name("client.cert.pem")
client_key_pem = pathlib.Path(__file__).with_name("client.key.pem")
ca_cert_pem = pathlib.Path(__file__).with_name("ca.cert.pem")
ssl_context.load_cert_chain(certfile=client_cert_pem, keyfile=client_key_pem)
ssl_context.load_verify_locations(ca_cert_pem)
# websocket producer uri wss, not ws
uri = "wss://localhost:8080/ws/v2/producer/persistent/public/default/testtopic"
client_pem = pathlib.Path(__file__).with_name("pulsar_client.pem")
ssl_context.load_verify_locations(client_pem)
# websocket producer uri wss, not ws
uri = "wss://localhost:8080/ws/v2/producer/persistent/public/default/testtopic"
# encode message
s = "Hello World"
firstEncoded = s.encode("UTF-8")
binaryEncoded = base64.b64encode(firstEncoded)
payloadString = binaryEncoded.decode('UTF-8')
async def producer_handler(websocket):
await websocket.send(json.dumps({
'payload' : payloadString,
'properties': {
'key1' : 'value1',
'key2' : 'value2'
},
'context' : 5
}))
async def test():
async with websockets.connect(uri) as websocket:
await producer_handler(websocket)
message = await websocket.recv()
print(f"< {message}")
asyncio.run(test())
note
conf/client.conf파일의 필수 구성 외에, WebSocket 서비스에서 TLS 암호화를 활성화하려면conf/broker.conf파일에 더 많은 파라미터를 구성해야 해요. 자세한 내용은 WebSocket 보안 설정을 참고해요.
5단계: CLI 도구 구성 (Step 5: Configure CLI tools)
pulsar-admin, pulsar-perf, pulsar-client 같은 커맨드라인 도구는 Pulsar 설치의 conf/client.conf 구성 파일을 사용해요.
Pulsar CLI 도구와 mTLS 암호화를 사용하려면 conf/client.conf 파일에 다음 파라미터를 추가해야 해요.
webServiceUrl=https://localhost:8081/
brokerServiceUrl=pulsar+ssl://localhost:6651/
authPlugin=org.apache.pulsar.client.impl.auth.AuthenticationTls
authParams=tlsCertFile:/path/to/admin.cert.pem,tlsKeyFile:/path/to/admin.key-pk8.pem
KeyStore로 mTLS 암호화 구성 (Configure mTLS encryption with KeyStore)
기본적으로 Pulsar는 브로커 서비스와 웹 서비스 모두에서 Conscrypt를 사용해요.
KeyStore로 mTLS 암호화를 구성하려면 다음 단계를 완료해요.
1단계: JKS 인증서 생성 (Step 1: Generate JKS certificate)
Java의 keytool 유틸리티를 사용해 클러스터의 각 머신에 대한 키와 인증서를 생성할 수 있어요.
DAYS=365
CLIENT_COMMON_PARAMS="-storetype JKS -storepass clientpw -keypass clientpw -noprompt"
BROKER_COMMON_PARAMS="-storetype JKS -storepass brokerpw -keypass brokerpw -noprompt"
# create keystore
keytool -genkeypair -keystore broker.keystore.jks ${BROKER_COMMON_PARAMS} -keyalg RSA -keysize 2048 -alias broker -validity $DAYS \
-dname 'CN=broker,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown'
keytool -genkeypair -keystore client.keystore.jks ${CLIENT_COMMON_PARAMS} -keyalg RSA -keysize 2048 -alias client -validity $DAYS \
-dname 'CN=client,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown'
# export certificate
keytool -exportcert -keystore broker.keystore.jks ${BROKER_COMMON_PARAMS} -file broker.cer -alias broker
keytool -exportcert -keystore client.keystore.jks ${CLIENT_COMMON_PARAMS} -file client.cer -alias client
# generate truststore
keytool -importcert -keystore client.truststore.jks ${CLIENT_COMMON_PARAMS} -file broker.cer -alias truststore
keytool -importcert -keystore broker.truststore.jks ${BROKER_COMMON_PARAMS} -file client.cer -alias truststore
note 호스트 이름 검증을 구성하려면
BROKER_COMMON_PARAMS값에 SAN(Subject Alternative Name)으로-ext SAN=IP:127.0.0.1,IP:192.168.20.2,DNS:broker.example.com를 추가해야 해요.
2단계: 브로커 구성 (Step 2: Configure brokers)
conf/broker.conf 파일에서 다음 파라미터를 구성하고 파일시스템 권한으로 스토어 파일에 대한 접근을 제한해요.
brokerServicePortTls=6651
webServicePortTls=8081
# Trusted client certificates are required to connect TLS
# Reject the Connection if the Client Certificate is not trusted.
# In effect, this requires that all connecting clients perform TLS client
# authentication.
tlsRequireTrustedClientCertOnConnect=true
tlsEnabledWithKeyStore=true
# key store
tlsKeyStoreType=JKS
tlsKeyStore=/var/private/tls/broker.keystore.jks
tlsKeyStorePassword=brokerpw
# trust store
tlsTrustStoreType=JKS
tlsTrustStore=/var/private/tls/broker.truststore.jks
tlsTrustStorePassword=brokerpw
# internal client/admin-client config
brokerClientTlsEnabled=true
brokerClientTlsEnabledWithKeyStore=true
brokerClientTlsTrustStoreType=JKS
brokerClientTlsTrustStore=/var/private/tls/client.truststore.jks
brokerClientTlsTrustStorePassword=clientpw
brokerClientTlsKeyStoreType=JKS
brokerClientTlsKeyStore=/var/private/tls/client.keystore.jks
brokerClientTlsKeyStorePassword=clientpw
비TLS 포트를 비활성화하려면 brokerServicePort와 webServicePort의 값을 비워야 해요.
note
tlsRequireTrustedClientCertOnConnect의 기본값은false로, 단방향 TLS를 나타내요.true로 설정하면(상호 TLS 활성화) 브로커/프록시는 신뢰할 수 있는 클라이언트 인증서를 요구하고, 그렇지 않으면 브로커/프록시는 클라이언트의 연결 요청을 거부해요.
3단계: 프록시 구성 (Step 3: Configure proxies)
프록시에서 mTLS 구성은 클라이언트→프록시, 프록시→브로커 두 방향의 연결을 포함해요.
servicePortTls=6651
webServicePortTls=8081
tlsRequireTrustedClientCertOnConnect=true
# keystore
tlsKeyStoreType=JKS
tlsKeyStore=/var/private/tls/proxy.keystore.jks
tlsKeyStorePassword=brokerpw
# truststore
tlsTrustStoreType=JKS
tlsTrustStore=/var/private/tls/proxy.truststore.jks
tlsTrustStorePassword=brokerpw
# internal client/admin-client config
tlsEnabledWithKeyStore=true
brokerClientTlsEnabled=true
brokerClientTlsEnabledWithKeyStore=true
brokerClientTlsTrustStoreType=JKS
brokerClientTlsTrustStore=/var/private/tls/client.truststore.jks
brokerClientTlsTrustStorePassword=clientpw
brokerClientTlsKeyStoreType=JKS
brokerClientTlsKeyStore=/var/private/tls/client.keystore.jks
brokerClientTlsKeyStorePassword=clientpw
4단계: 클라이언트 구성 (Step 4: Configure clients)
PEM으로 mTLS 암호화 구성과 유사하게, 최소 구성으로 TrustStore 정보를 제공해야 해요.
다음은 예시예요.
- Java client
- Java admin client
Java client:
import org.apache.pulsar.client.api.PulsarClient;
PulsarClient client = PulsarClient.builder()
.serviceUrl("pulsar+ssl://broker.example.com:6651/")
.useKeyStoreTls(true)
.tlsTrustStoreType("JKS")
.tlsTrustStorePath("/var/private/tls/client.truststore.jks")
.tlsTrustStorePassword("clientpw")
.tlsKeyStoreType("JKS")
.tlsKeyStorePath("/var/private/tls/client.keystore.jks")
.tlsKeyStorePassword("clientpw")
.enableTlsHostnameVerification(true) // enabled by default since 5.0
.allowTlsInsecureConnection(false) // false by default, in any case
.build();
note
useKeyStoreTls를true로 설정하면tlsTrustStorePath를 구성해야 해요.
Java admin client:
PulsarAdmin amdin = PulsarAdmin.builder().serviceHttpUrl("https://broker.example.com:8443")
.tlsTrustStoreType("JKS")
.tlsTrustStorePath("/var/private/tls/client.truststore.jks")
.tlsTrustStorePassword("clientpw")
.tlsKeyStoreType("JKS")
.tlsKeyStorePath("/var/private/tls/client.keystore.jks")
.tlsKeyStorePassword("clientpw")
.enableTlsHostnameVerification(true) // enabled by default since 5.0
.allowTlsInsecureConnection(false) // false by default, in any case
.build();
5단계: CLI 도구 구성 (Step 5: Configure CLI tools)
pulsar-admin, pulsar-perf, pulsar-client 같은 커맨드라인 도구의 경우 Pulsar 설치의 conf/client.conf 구성 파일을 사용해요.
authPlugin=org.apache.pulsar.client.impl.auth.AuthenticationKeyStoreTls
authParams={"keyStoreType":"JKS","keyStorePath":"/var/private/tls/client.keystore.jks","keyStorePassword":"clientpw"}
TLS 로깅 활성화 (Enable TLS Logging)
브로커 및/또는 클라이언트를 javax.net.debug 시스템 속성으로 시작하면 JVM 레벨에서 TLS 디버그 로깅을 활성화할 수 있어요. 예:
-Djavax.net.debug=all
자세한 내용은 Oracle documentation을 참고해요.
더 알아보기 (Learn more)
- mTLS 인증 구성은 mTLS authentication 문서를 참고해요.
- 인증의 기본 개념은 Security overview 문서를 봐요.
- WebSocket 클라이언트 보안 설정은 WebSocket 문서를 살펴봐요.