26
26
import org .elasticsearch .action .update .UpdateAction ;
27
27
import org .elasticsearch .action .update .UpdateRequestBuilder ;
28
28
import org .elasticsearch .client .Client ;
29
+ import org .elasticsearch .cluster .ClusterState ;
30
+ import org .elasticsearch .cluster .node .DiscoveryNode ;
31
+ import org .elasticsearch .cluster .node .DiscoveryNodes ;
29
32
import org .elasticsearch .cluster .service .ClusterService ;
30
33
import org .elasticsearch .common .settings .MockSecureSettings ;
31
34
import org .elasticsearch .common .Strings ;
44
47
import org .elasticsearch .test .ClusterServiceUtils ;
45
48
import org .elasticsearch .test .ESTestCase ;
46
49
import org .elasticsearch .test .EqualsHashCodeTestUtils ;
50
+ import org .elasticsearch .test .VersionUtils ;
47
51
import org .elasticsearch .threadpool .FixedExecutorBuilder ;
48
52
import org .elasticsearch .threadpool .ThreadPool ;
49
53
import org .elasticsearch .xpack .core .XPackSettings ;
53
57
import org .elasticsearch .xpack .core .security .user .User ;
54
58
import org .elasticsearch .xpack .core .watcher .watch .ClockMock ;
55
59
import org .elasticsearch .xpack .security .support .SecurityIndexManager ;
60
+ import org .junit .After ;
56
61
import org .junit .AfterClass ;
57
62
import org .junit .Before ;
58
63
import org .junit .BeforeClass ;
66
71
import java .time .temporal .ChronoUnit ;
67
72
import java .util .Base64 ;
68
73
import java .util .Collections ;
74
+ import java .util .EnumSet ;
69
75
import java .util .HashMap ;
70
76
import java .util .Map ;
71
77
import java .util .concurrent .ExecutionException ;
@@ -91,6 +97,7 @@ public class TokenServiceTests extends ESTestCase {
91
97
private Client client ;
92
98
private SecurityIndexManager securityIndex ;
93
99
private ClusterService clusterService ;
100
+ private boolean mixedCluster ;
94
101
private Settings tokenServiceEnabledSettings = Settings .builder ()
95
102
.put (XPackSettings .TOKEN_SERVICE_ENABLED_SETTING .getKey (), true ).build ();
96
103
@@ -141,6 +148,25 @@ public void setupClient() {
141
148
return null ;
142
149
}).when (securityIndex ).prepareIndexIfNeededThenExecute (any (Consumer .class ), any (Runnable .class ));
143
150
this .clusterService = ClusterServiceUtils .createClusterService (threadPool );
151
+ this .mixedCluster = randomBoolean ();
152
+ if (mixedCluster ) {
153
+ Version version = VersionUtils .randomVersionBetween (random (), Version .V_5_6_0 , Version .V_5_6_10 );
154
+ logger .info ("adding a node with version [{}] to the cluster service" , version );
155
+ ClusterState updatedState = ClusterState .builder (clusterService .state ())
156
+ .nodes (DiscoveryNodes .builder (clusterService .state ().nodes ())
157
+ .add (new DiscoveryNode ("56node" , ESTestCase .buildNewFakeTransportAddress (), Collections .emptyMap (),
158
+ EnumSet .allOf (DiscoveryNode .Role .class ), version ))
159
+ .build ())
160
+ .build ();
161
+ ClusterServiceUtils .setState (clusterService , updatedState );
162
+ }
163
+ }
164
+
165
+ @ After
166
+ public void stopClusterService () {
167
+ if (clusterService != null ) {
168
+ clusterService .close ();
169
+ }
144
170
}
145
171
146
172
@ BeforeClass
@@ -172,7 +198,7 @@ public void testAttachAndGetToken() throws Exception {
172
198
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
173
199
tokenService .getAndValidateToken (requestContext , future );
174
200
UserToken serialized = future .get ();
175
- assertEquals (authentication , serialized .getAuthentication ());
201
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
176
202
}
177
203
178
204
try (ThreadContext .StoredContext ignore = requestContext .newStoredContext (true )) {
@@ -183,11 +209,12 @@ public void testAttachAndGetToken() throws Exception {
183
209
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
184
210
anotherService .getAndValidateToken (requestContext , future );
185
211
UserToken fromOtherService = future .get ();
186
- assertEquals (authentication , fromOtherService .getAuthentication ());
212
+ assertAuthenticationEquals (authentication , fromOtherService .getAuthentication ());
187
213
}
188
214
}
189
215
190
216
public void testRotateKey () throws Exception {
217
+ assumeFalse ("internally managed keys do not work in a mixed cluster" , mixedCluster );
191
218
TokenService tokenService = new TokenService (tokenServiceEnabledSettings , systemUTC (), client , securityIndex , clusterService );
192
219
Authentication authentication = new Authentication (new User ("joe" , "admin" ), new RealmRef ("native_realm" , "native" , "node1" ), null );
193
220
PlainActionFuture <Tuple <UserToken , String >> tokenFuture = new PlainActionFuture <>();
@@ -203,15 +230,15 @@ public void testRotateKey() throws Exception {
203
230
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
204
231
tokenService .getAndValidateToken (requestContext , future );
205
232
UserToken serialized = future .get ();
206
- assertEquals (authentication , serialized .getAuthentication ());
233
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
207
234
}
208
235
rotateKeys (tokenService );
209
236
210
237
try (ThreadContext .StoredContext ignore = requestContext .newStoredContext (true )) {
211
238
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
212
239
tokenService .getAndValidateToken (requestContext , future );
213
240
UserToken serialized = future .get ();
214
- assertEquals (authentication , serialized .getAuthentication ());
241
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
215
242
}
216
243
217
244
PlainActionFuture <Tuple <UserToken , String >> newTokenFuture = new PlainActionFuture <>();
@@ -240,6 +267,7 @@ private void rotateKeys(TokenService tokenService) {
240
267
}
241
268
242
269
public void testKeyExchange () throws Exception {
270
+ assumeFalse ("internally managed keys do not work in a mixed cluster" , mixedCluster );
243
271
TokenService tokenService = new TokenService (tokenServiceEnabledSettings , systemUTC (), client , securityIndex , clusterService );
244
272
int numRotations = 0 ;randomIntBetween (1 , 5 );
245
273
for (int i = 0 ; i < numRotations ; i ++) {
@@ -261,7 +289,7 @@ public void testKeyExchange() throws Exception {
261
289
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
262
290
otherTokenService .getAndValidateToken (requestContext , future );
263
291
UserToken serialized = future .get ();
264
- assertEquals (authentication , serialized .getAuthentication ());
292
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
265
293
}
266
294
267
295
rotateKeys (tokenService );
@@ -272,11 +300,12 @@ public void testKeyExchange() throws Exception {
272
300
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
273
301
otherTokenService .getAndValidateToken (requestContext , future );
274
302
UserToken serialized = future .get ();
275
- assertEquals (authentication , serialized .getAuthentication ());
303
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
276
304
}
277
305
}
278
306
279
307
public void testPruneKeys () throws Exception {
308
+ assumeFalse ("internally managed keys do not work in a mixed cluster" , mixedCluster );
280
309
TokenService tokenService = new TokenService (tokenServiceEnabledSettings , systemUTC (), client , securityIndex , clusterService );
281
310
Authentication authentication = new Authentication (new User ("joe" , "admin" ), new RealmRef ("native_realm" , "native" , "node1" ), null );
282
311
PlainActionFuture <Tuple <UserToken , String >> tokenFuture = new PlainActionFuture <>();
@@ -292,7 +321,7 @@ public void testPruneKeys() throws Exception {
292
321
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
293
322
tokenService .getAndValidateToken (requestContext , future );
294
323
UserToken serialized = future .get ();
295
- assertEquals (authentication , serialized .getAuthentication ());
324
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
296
325
}
297
326
TokenMetaData metaData = tokenService .pruneKeys (randomIntBetween (0 , 100 ));
298
327
tokenService .refreshMetaData (metaData );
@@ -306,7 +335,7 @@ public void testPruneKeys() throws Exception {
306
335
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
307
336
tokenService .getAndValidateToken (requestContext , future );
308
337
UserToken serialized = future .get ();
309
- assertEquals (authentication , serialized .getAuthentication ());
338
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
310
339
}
311
340
312
341
PlainActionFuture <Tuple <UserToken , String >> newTokenFuture = new PlainActionFuture <>();
@@ -332,7 +361,7 @@ public void testPruneKeys() throws Exception {
332
361
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
333
362
tokenService .getAndValidateToken (requestContext , future );
334
363
UserToken serialized = future .get ();
335
- assertEquals (authentication , serialized .getAuthentication ());
364
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
336
365
}
337
366
338
367
}
@@ -353,7 +382,7 @@ public void testPassphraseWorks() throws Exception {
353
382
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
354
383
tokenService .getAndValidateToken (requestContext , future );
355
384
UserToken serialized = future .get ();
356
- assertEquals (authentication , serialized .getAuthentication ());
385
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
357
386
}
358
387
359
388
try (ThreadContext .StoredContext ignore = requestContext .newStoredContext (true )) {
@@ -454,7 +483,7 @@ public void testTokenExpiry() throws Exception {
454
483
// the clock is still frozen, so the cookie should be valid
455
484
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
456
485
tokenService .getAndValidateToken (requestContext , future );
457
- assertEquals (authentication , future .get ().getAuthentication ());
486
+ assertAuthenticationEquals (authentication , future .get ().getAuthentication ());
458
487
}
459
488
460
489
final TimeValue defaultExpiration = TokenService .TOKEN_EXPIRATION .get (Settings .EMPTY );
@@ -464,7 +493,7 @@ public void testTokenExpiry() throws Exception {
464
493
clock .fastForwardSeconds (fastForwardAmount );
465
494
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
466
495
tokenService .getAndValidateToken (requestContext , future );
467
- assertEquals (authentication , future .get ().getAuthentication ());
496
+ assertAuthenticationEquals (authentication , future .get ().getAuthentication ());
468
497
}
469
498
470
499
try (ThreadContext .StoredContext ignore = requestContext .newStoredContext (true )) {
@@ -473,7 +502,7 @@ public void testTokenExpiry() throws Exception {
473
502
clock .rewind (TimeValue .timeValueNanos (clock .instant ().getNano ())); // trim off nanoseconds since don't store them in the index
474
503
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
475
504
tokenService .getAndValidateToken (requestContext , future );
476
- assertEquals (authentication , future .get ().getAuthentication ());
505
+ assertAuthenticationEquals (authentication , future .get ().getAuthentication ());
477
506
}
478
507
479
508
try (ThreadContext .StoredContext ignore = requestContext .newStoredContext (true )) {
@@ -569,7 +598,7 @@ public void testIndexNotAvailable() throws Exception {
569
598
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
570
599
tokenService .getAndValidateToken (requestContext , future );
571
600
UserToken serialized = future .get ();
572
- assertEquals (authentication , serialized .getAuthentication ());
601
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
573
602
574
603
when (securityIndex .isAvailable ()).thenReturn (false );
575
604
when (securityIndex .indexExists ()).thenReturn (true );
@@ -601,6 +630,7 @@ public void testDecodePre6xToken() throws GeneralSecurityException, ExecutionExc
601
630
assertWarnings ("[xpack.security.authc.token.passphrase] setting was deprecated in Elasticsearch and will be removed in a future" +
602
631
" release! See the breaking changes documentation for the next major version." );
603
632
}
633
+
604
634
public void testGetAuthenticationWorksWithExpiredToken () throws Exception {
605
635
TokenService tokenService =
606
636
new TokenService (tokenServiceEnabledSettings , Clock .systemUTC (), client , securityIndex , clusterService );
@@ -611,7 +641,7 @@ public void testGetAuthenticationWorksWithExpiredToken() throws Exception {
611
641
PlainActionFuture <Tuple <Authentication , Map <String , Object >>> authFuture = new PlainActionFuture <>();
612
642
tokenService .getAuthenticationAndMetaData (userTokenString , authFuture );
613
643
Authentication retrievedAuth = authFuture .actionGet ().v1 ();
614
- assertEquals (authentication , retrievedAuth );
644
+ assertAuthenticationEquals (authentication , retrievedAuth );
615
645
}
616
646
617
647
private void mockGetTokenFromId (UserToken userToken ) {
@@ -638,4 +668,16 @@ public static void mockGetTokenFromId(UserToken userToken, Client client) {
638
668
return Void .TYPE ;
639
669
}).when (client ).get (any (GetRequest .class ), any (ActionListener .class ));
640
670
}
671
+
672
+ private void assertAuthenticationEquals (Authentication expected , Authentication actual ) {
673
+ if (mixedCluster ) {
674
+ assertNotNull (expected );
675
+ assertNotNull (actual );
676
+ assertEquals (expected .getUser (), actual .getUser ());
677
+ assertEquals (expected .getAuthenticatedBy (), actual .getAuthenticatedBy ());
678
+ assertEquals (expected .getLookedUpBy (), actual .getLookedUpBy ());
679
+ } else {
680
+ assertEquals (expected , actual );
681
+ }
682
+ }
641
683
}
0 commit comments