로컬 환경에서는 Elasticsearch와의 통신이 정상적으로 이루어졌지만, Docker 환경에서 배포 후 애플리케이션이 Elasticsearch에 연결하려고 할 때 PKIX path building failed
오류가 발생했습니다. 이는 Elasticsearch의 인증서를 신뢰할 수 없는 문제로 인해 Java의 TrustStore
에서 유효성을 확인하지 못하기 때문에 발생하는 문제입니다.
TrustStore
에 등록되지 않았기 때문에 신뢰할 수 없는 인증서로 인식됨Docker 컨테이너 내에서 Elasticsearch의 인증서를 신뢰하도록 TrustStore
에 추가해야 합니다. 이를 위해 Dockerfile
을 수정하여 인증서를 추가하는 과정을 포함했습니다.
# Elasticsearch CA 인증서 복사
COPY esCert/elasticsearch.crt /usr/local/share/ca-certificates/ca.crt
# Java TrustStore에 `ca.crt` 등록
RUN keytool -import -trustcacerts -keystore /usr/local/openjdk-17/lib/security/cacerts \
-storepass changeit -noprompt -alias elasticsearch-root-ca \
-file /usr/local/share/ca-certificates/ca.crt
이렇게 하면 Elasticsearch의 CA 인증서를 Java의 TrustStore에 등록하여 신뢰할 수 있도록 설정할 수 있습니다.
기존에는 애플리케이션 코드에서 SSLContext
를 수동으로 생성하여 인증서를 로드했지만, 이를 JVM 기본 TrustStore
를 사용하도록 변경하여 인증서 관리를 단순화했습니다.
private SSLContext getSSLContext() throws Exception {
byte[] decodedCertificate = Base64.getMimeDecoder().decode(certificateBase64);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate ca;
try (InputStream certificateInputStream = new ByteArrayInputStream(decodedCertificate)) {
ca = (X509Certificate) certificateFactory.generateCertificate(certificateInputStream);
}
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), new java.security.SecureRandom());
return sslContext;
}
@Bean
public RestClient restClient() throws Exception {
// JVM 기본 TrustStore 사용 (별도의 인증서 로드 필요 없음)
SSLContext sslContext = SSLContext.getDefault();
RestClientBuilder builder = RestClient.builder(new HttpHost(host, port, "https"))
.setHttpClientConfigCallback(httpAsyncClientBuilder -> httpAsyncClientBuilder
.setSSLContext(sslContext) // TrustStore 사용
.setDefaultCredentialsProvider(credentialsProvider()));
return builder.build();
}
Docker 환경에서 애플리케이션을 실행할 때 Elasticsearch의 CA 인증서를 신뢰하도록 하기 위해 Dockerfile
을 수정했습니다.
# Base Image
FROM openjdk:17-jdk-slim
# 작업 디렉토리 설정
WORKDIR /app
# Elasticsearch CA 인증서 복사
COPY esCert/elasticsearch.crt /usr/local/share/ca-certificates/ca.crt
# Java TrustStore에 `ca.crt` 등록
RUN keytool -import -trustcacerts -keystore /usr/local/openjdk-17/lib/security/cacerts \
-storepass changeit -noprompt -alias elasticsearch-root-ca \
-file /usr/local/share/ca-certificates/ca.crt
# JAR 파일 복사
COPY Ficket/ficket-search/build/libs/ficket-search-0.0.1-SNAPSHOT.jar app.jar
# 애플리케이션 실행 포트
EXPOSE 8094
# 애플리케이션 실행
CMD ["java", "-Duser.timezone=Asia/Seoul", \
"-Dspring.application.name=search-service", \
"-Dspring.profiles.active=prod", \
"-Dspring.config.import=optional:configserver:http://config-server:8888", \
"-Djavax.net.ssl.trustStore=/usr/local/openjdk-17/lib/security/cacerts", \
"-Djavax.net.ssl.trustStorePassword=changeit", \
"-jar", "app.jar"]
이제 Elasticsearch의 인증서를 Docker 컨테이너 내부에서 올바르게 신뢰하도록 설정할 수 있으며, 이를 통해 PKIX path building failed
오류를 해결할 수 있습니다.