1
1
package org .testcontainers .elasticsearch ;
2
2
3
- import com .github .dockerjava .api .command .InspectContainerResponse ;
4
3
import com .github .dockerjava .api .exception .NotFoundException ;
5
4
import lombok .extern .slf4j .Slf4j ;
6
5
import org .apache .commons .io .IOUtils ;
@@ -66,6 +65,9 @@ public class ElasticsearchContainer extends GenericContainer<ElasticsearchContai
66
65
67
66
private static final DockerImageName ELASTICSEARCH_IMAGE_NAME = DockerImageName .parse ("elasticsearch" );
68
67
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
+
69
71
/**
70
72
* Elasticsearch Default version
71
73
*/
@@ -77,9 +79,7 @@ public class ElasticsearchContainer extends GenericContainer<ElasticsearchContai
77
79
78
80
private final boolean isAtLeastMajorVersion8 ;
79
81
80
- private Optional <byte []> caCertAsBytes = Optional .empty ();
81
-
82
- private String certPath = "/usr/share/elasticsearch/config/certs/http_ca.crt" ;
82
+ private String certPath = "" ;
83
83
84
84
/**
85
85
* @deprecated use {@link #ElasticsearchContainer(DockerImageName)} instead
@@ -91,6 +91,7 @@ public ElasticsearchContainer() {
91
91
92
92
/**
93
93
* Create an Elasticsearch Container by passing the full docker image name
94
+ *
94
95
* @param dockerImageName Full docker image name as a {@link String}, like: docker.elastic.co/elasticsearch/elasticsearch:7.9.2
95
96
*/
96
97
public ElasticsearchContainer (String dockerImageName ) {
@@ -99,6 +100,7 @@ public ElasticsearchContainer(String dockerImageName) {
99
100
100
101
/**
101
102
* Create an Elasticsearch Container by passing the full docker image name
103
+ *
102
104
* @param dockerImageName Full docker image name as a {@link DockerImageName}, like: DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch:7.9.2")
103
105
*/
104
106
public ElasticsearchContainer (final DockerImageName dockerImageName ) {
@@ -136,23 +138,7 @@ public ElasticsearchContainer(final DockerImageName dockerImageName) {
136
138
setWaitStrategy (new LogMessageWaitStrategy ().withRegEx (regex ));
137
139
if (isAtLeastMajorVersion8 ) {
138
140
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 );
156
142
}
157
143
}
158
144
@@ -162,17 +148,36 @@ protected void containerIsStarted(InspectContainerResponse containerInfo) {
162
148
* @return byte array optional containing the CA cert extracted from the docker container
163
149
*/
164
150
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 ();
166
166
}
167
167
168
168
/**
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
170
170
* @return a customized SSL Context
171
171
*/
172
172
public SSLContext createSslContextFromCa () {
173
173
try {
174
174
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
+ );
176
181
KeyStore trustStore = KeyStore .getInstance ("pkcs12" );
177
182
trustStore .load (null , null );
178
183
trustStore .setCertificateEntry ("ca" , trustedCa );
@@ -190,13 +195,13 @@ public SSLContext createSslContextFromCa() {
190
195
/**
191
196
* Define the Elasticsearch password to set. It enables security behind the scene for major version below 8.0.0.
192
197
* It's not possible to use security with the oss image.
193
- * @param password Password to set
198
+ * @param password Password to set
194
199
* @return this
195
200
*/
196
201
public ElasticsearchContainer withPassword (String password ) {
197
202
if (isOss ) {
198
203
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"
200
205
);
201
206
}
202
207
withEnv ("ELASTIC_PASSWORD" , password );
@@ -222,7 +227,8 @@ public String getHttpHostAddress() {
222
227
return getHost () + ":" + getMappedPort (ELASTICSEARCH_DEFAULT_PORT );
223
228
}
224
229
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
226
232
public InetSocketAddress getTcpHost () {
227
233
return new InetSocketAddress (getHost (), getMappedPort (ELASTICSEARCH_DEFAULT_TCP_PORT ));
228
234
}
0 commit comments