11package org .testcontainers .elasticsearch ;
22
3- import com .github .dockerjava .api .command .InspectContainerResponse ;
43import com .github .dockerjava .api .exception .NotFoundException ;
54import lombok .extern .slf4j .Slf4j ;
65import org .apache .commons .io .IOUtils ;
@@ -66,6 +65,9 @@ public class ElasticsearchContainer extends GenericContainer<ElasticsearchContai
6665
6766 private static final DockerImageName ELASTICSEARCH_IMAGE_NAME = DockerImageName .parse ("elasticsearch" );
6867
68+ // default location of the automatically generated self-signed HTTP cert for versions >= 8
69+ private static final String DEFAULT_CERT_PATH = "/usr/share/elasticsearch/config/certs/http_ca.crt" ;
70+
6971 /**
7072 * Elasticsearch Default version
7173 */
@@ -77,9 +79,7 @@ public class ElasticsearchContainer extends GenericContainer<ElasticsearchContai
7779
7880 private final boolean isAtLeastMajorVersion8 ;
7981
80- private Optional <byte []> caCertAsBytes = Optional .empty ();
81-
82- private String certPath = "/usr/share/elasticsearch/config/certs/http_ca.crt" ;
82+ private String certPath = "" ;
8383
8484 /**
8585 * @deprecated use {@link #ElasticsearchContainer(DockerImageName)} instead
@@ -91,6 +91,7 @@ public ElasticsearchContainer() {
9191
9292 /**
9393 * Create an Elasticsearch Container by passing the full docker image name
94+ *
9495 * @param dockerImageName Full docker image name as a {@link String}, like: docker.elastic.co/elasticsearch/elasticsearch:7.9.2
9596 */
9697 public ElasticsearchContainer (String dockerImageName ) {
@@ -99,6 +100,7 @@ public ElasticsearchContainer(String dockerImageName) {
99100
100101 /**
101102 * Create an Elasticsearch Container by passing the full docker image name
103+ *
102104 * @param dockerImageName Full docker image name as a {@link DockerImageName}, like: DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch:7.9.2")
103105 */
104106 public ElasticsearchContainer (final DockerImageName dockerImageName ) {
@@ -136,23 +138,7 @@ public ElasticsearchContainer(final DockerImageName dockerImageName) {
136138 setWaitStrategy (new LogMessageWaitStrategy ().withRegEx (regex ));
137139 if (isAtLeastMajorVersion8 ) {
138140 withPassword (ELASTICSEARCH_DEFAULT_PASSWORD );
139- }
140- }
141-
142- @ Override
143- protected void containerIsStarted (InspectContainerResponse containerInfo ) {
144- if (isAtLeastMajorVersion8 && StringUtils .isNotEmpty (certPath )) {
145- try {
146- byte [] bytes = copyFileFromContainer (certPath , IOUtils ::toByteArray );
147- if (bytes .length > 0 ) {
148- this .caCertAsBytes = Optional .of (bytes );
149- }
150- } catch (NotFoundException e ) {
151- // just emit an error message, but do not throw an exception
152- // this might be ok, if the docker image is accidentally looking like version 8 or latest
153- // can happen if Elasticsearch is repackaged, i.e. with custom plugins
154- log .warn ("CA cert under " + certPath + " not found." );
155- }
141+ withCertPath (DEFAULT_CERT_PATH );
156142 }
157143 }
158144
@@ -162,17 +148,36 @@ protected void containerIsStarted(InspectContainerResponse containerInfo) {
162148 * @return byte array optional containing the CA cert extracted from the docker container
163149 */
164150 public Optional <byte []> caCertAsBytes () {
165- return caCertAsBytes ;
151+ if (StringUtils .isBlank (certPath )) {
152+ return Optional .empty ();
153+ }
154+ try {
155+ byte [] bytes = copyFileFromContainer (certPath , IOUtils ::toByteArray );
156+ if (bytes .length > 0 ) {
157+ return Optional .of (bytes );
158+ }
159+ } catch (NotFoundException e ) {
160+ // just emit an error message, but do not throw an exception
161+ // this might be ok, if the docker image is accidentally looking like version 8 or latest
162+ // can happen if Elasticsearch is repackaged, i.e. with custom plugins
163+ log .warn ("CA cert under " + certPath + " not found." );
164+ }
165+ return Optional .empty ();
166166 }
167167
168168 /**
169- * A SSL context based on the self signed CA, so that using this SSL Context allows to connect to the Elasticsearch service
169+ * A SSL context based on the self- signed CA, so that using this SSL Context allows to connect to the Elasticsearch service
170170 * @return a customized SSL Context
171171 */
172172 public SSLContext createSslContextFromCa () {
173173 try {
174174 CertificateFactory factory = CertificateFactory .getInstance ("X.509" );
175- Certificate trustedCa = factory .generateCertificate (new ByteArrayInputStream (caCertAsBytes .get ()));
175+ Certificate trustedCa = factory .generateCertificate (
176+ new ByteArrayInputStream (
177+ caCertAsBytes ()
178+ .orElseThrow (() -> new IllegalStateException ("CA cert under " + certPath + " not found." ))
179+ )
180+ );
176181 KeyStore trustStore = KeyStore .getInstance ("pkcs12" );
177182 trustStore .load (null , null );
178183 trustStore .setCertificateEntry ("ca" , trustedCa );
@@ -190,13 +195,13 @@ public SSLContext createSslContextFromCa() {
190195 /**
191196 * Define the Elasticsearch password to set. It enables security behind the scene for major version below 8.0.0.
192197 * It's not possible to use security with the oss image.
193- * @param password Password to set
198+ * @param password Password to set
194199 * @return this
195200 */
196201 public ElasticsearchContainer withPassword (String password ) {
197202 if (isOss ) {
198203 throw new IllegalArgumentException (
199- "You can not activate security on Elastic OSS Image. " + " Please switch to the default distribution"
204+ "You can not activate security on Elastic OSS Image. Please switch to the default distribution"
200205 );
201206 }
202207 withEnv ("ELASTIC_PASSWORD" , password );
@@ -222,7 +227,8 @@ public String getHttpHostAddress() {
222227 return getHost () + ":" + getMappedPort (ELASTICSEARCH_DEFAULT_PORT );
223228 }
224229
225- @ Deprecated // The TransportClient will be removed in Elasticsearch 8. No need to expose this port anymore in the future.
230+ // The TransportClient will be removed in Elasticsearch 8. No need to expose this port anymore in the future.
231+ @ Deprecated
226232 public InetSocketAddress getTcpHost () {
227233 return new InetSocketAddress (getHost (), getMappedPort (ELASTICSEARCH_DEFAULT_TCP_PORT ));
228234 }
0 commit comments