15
15
16
16
package io .confluent .connect .elasticsearch .helper ;
17
17
18
- import io .confluent .connect .elasticsearch .ElasticsearchClient ;
19
- import io .confluent .connect .elasticsearch .RetryUtil ;
18
+ import co .elastic .clients .elasticsearch .security .GrantApiKeyResponse ;
20
19
import org .apache .kafka .common .config .SslConfigs ;
21
- import org .apache .kafka .test .TestUtils ;
22
20
import org .elasticsearch .client .security .user .User ;
23
21
import org .elasticsearch .client .security .user .privileges .Role ;
24
22
import org .slf4j .Logger ;
25
23
import org .slf4j .LoggerFactory ;
26
24
import org .testcontainers .containers .ContainerLaunchException ;
27
25
import org .testcontainers .containers .output .OutputFrame ;
28
26
import org .testcontainers .containers .wait .strategy .Wait ;
29
- import org .testcontainers .containers .wait .strategy .WaitStrategyTarget ;
30
- import org .testcontainers .images .RemoteDockerImage ;
31
27
import org .testcontainers .images .builder .ImageFromDockerfile ;
32
28
import org .testcontainers .images .builder .dockerfile .DockerfileBuilder ;
33
29
import org .testcontainers .shaded .org .apache .commons .io .IOUtils ;
34
- import org .testcontainers .utility .DockerImageName ;
35
30
36
31
import java .io .File ;
37
32
import java .io .FileOutputStream ;
40
35
import java .net .InetAddress ;
41
36
import java .net .URI ;
42
37
import java .net .URISyntaxException ;
38
+ import java .nio .charset .StandardCharsets ;
43
39
import java .time .Duration ;
44
40
import java .util .ArrayList ;
41
+ import java .util .Base64 ;
45
42
import java .util .HashMap ;
46
43
import java .util .List ;
47
44
import java .util .Map ;
@@ -147,6 +144,7 @@ public static ElasticsearchContainer withESVersion(String ESVersion) {
147
144
private Map <User , String > usersToCreate ;
148
145
private String localKeystorePath ;
149
146
private String localTruststorePath ;
147
+ private Map <String , String > apiKeysToCreate ;
150
148
151
149
/**
152
150
* Create an Elasticsearch container with the given image name with version qualifier.
@@ -179,6 +177,9 @@ public void start() {
179
177
ElasticsearchHelperClient helperClient = getHelperClient (props );
180
178
helperClient .waitForConnection (30000 );
181
179
createUsersAndRoles (helperClient );
180
+ if (isApikeyEnabled ()) {
181
+ createApikeys (helperClient );
182
+ }
182
183
}
183
184
}
184
185
@@ -204,6 +205,21 @@ private void createUsersAndRoles(ElasticsearchHelperClient helperClient ) {
204
205
}
205
206
}
206
207
208
+ private void createApikeys (ElasticsearchHelperClient helperClient ) {
209
+ try {
210
+ for (Map .Entry <User ,String > userToPassword : this .usersToCreate .entrySet ()) {
211
+ GrantApiKeyResponse grantApiKeyResponse = helperClient .grantApiKey (userToPassword , this .rolesToCreate );
212
+ String apiKey =
213
+ Base64 .getEncoder ().encodeToString (
214
+ (grantApiKeyResponse .id () + ":" + grantApiKeyResponse .apiKey ())
215
+ .getBytes (StandardCharsets .UTF_8 ));
216
+ apiKeysToCreate .put (userToPassword .getKey ().getUsername (), apiKey );
217
+ }
218
+ } catch (IOException e ) {
219
+ throw new ContainerLaunchException ("Container startup failed" , e );
220
+ }
221
+ }
222
+
207
223
public ElasticsearchContainer withSslEnabled (boolean enable ) {
208
224
enableSsl (enable );
209
225
return this ;
@@ -219,6 +235,12 @@ public ElasticsearchContainer withBasicAuth(Map<User, String> users, List<Role>
219
235
return this ;
220
236
}
221
237
238
+ public ElasticsearchContainer withApikey (Map <User , String > users , List <Role > roles ) {
239
+ enableBasicAuth (users , roles );
240
+ enableApikeys (users );
241
+ return this ;
242
+ }
243
+
222
244
/**
223
245
* Set whether the Elasticsearch instance should use SSL.
224
246
*
@@ -289,10 +311,24 @@ private void enableBasicAuth(Map<User, String> users, List<Role> roles) {
289
311
this .rolesToCreate = roles ;
290
312
}
291
313
314
+ private void enableApikeys (Map <User , String > users ) {
315
+ if (isKerberosEnabled ()) {
316
+ throw new IllegalStateException (
317
+ "Api Keys and Kerberos are mutually exclusive."
318
+ );
319
+ }
320
+ this .apiKeysToCreate = new HashMap <>();
321
+ users .keySet ().stream ().forEach (user -> this .apiKeysToCreate .put (user .getUsername (), null ));
322
+ }
323
+
292
324
public boolean isBasicAuthEnabled () {
293
325
return usersToCreate != null && !this .usersToCreate .isEmpty ();
294
326
}
295
327
328
+ public boolean isApikeyEnabled () {
329
+ return apiKeysToCreate != null && !this .apiKeysToCreate .isEmpty ();
330
+ }
331
+
296
332
private String getFullResourcePath (String resourceName ) {
297
333
if (isSslEnabled () && isKerberosEnabled ()) {
298
334
return "/both/" + resourceName ;
@@ -601,4 +637,8 @@ public boolean shouldStartClientInCompatibilityMode() {
601
637
public int esMajorVersion () {
602
638
return getImageVersion ().get (0 );
603
639
}
640
+
641
+ public Map <String , String > getAPIkeys () {
642
+ return apiKeysToCreate ;
643
+ }
604
644
}
0 commit comments