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 .SecurityLifecycleService ;
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 SecurityLifecycleService lifecycleService ;
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 (lifecycleService ).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
@@ -173,7 +199,7 @@ public void testAttachAndGetToken() throws Exception {
173
199
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
174
200
tokenService .getAndValidateToken (requestContext , future );
175
201
UserToken serialized = future .get ();
176
- assertEquals (authentication , serialized .getAuthentication ());
202
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
177
203
}
178
204
179
205
try (ThreadContext .StoredContext ignore = requestContext .newStoredContext (true )) {
@@ -184,13 +210,13 @@ public void testAttachAndGetToken() throws Exception {
184
210
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
185
211
anotherService .getAndValidateToken (requestContext , future );
186
212
UserToken fromOtherService = future .get ();
187
- assertEquals (authentication , fromOtherService .getAuthentication ());
213
+ assertAuthenticationEquals (authentication , fromOtherService .getAuthentication ());
188
214
}
189
215
}
190
216
191
217
public void testRotateKey () throws Exception {
192
- TokenService tokenService =
193
- new TokenService (tokenServiceEnabledSettings , systemUTC (), client , lifecycleService , clusterService );
218
+ assumeFalse ( "internally managed keys do not work in a mixed cluster" , mixedCluster );
219
+ TokenService tokenService = new TokenService (tokenServiceEnabledSettings , systemUTC (), client , lifecycleService , clusterService );
194
220
Authentication authentication = new Authentication (new User ("joe" , "admin" ), new RealmRef ("native_realm" , "native" , "node1" ), null );
195
221
PlainActionFuture <Tuple <UserToken , String >> tokenFuture = new PlainActionFuture <>();
196
222
tokenService .createUserToken (authentication , authentication , tokenFuture , Collections .emptyMap ());
@@ -205,15 +231,15 @@ public void testRotateKey() throws Exception {
205
231
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
206
232
tokenService .getAndValidateToken (requestContext , future );
207
233
UserToken serialized = future .get ();
208
- assertEquals (authentication , serialized .getAuthentication ());
234
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
209
235
}
210
236
rotateKeys (tokenService );
211
237
212
238
try (ThreadContext .StoredContext ignore = requestContext .newStoredContext (true )) {
213
239
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
214
240
tokenService .getAndValidateToken (requestContext , future );
215
241
UserToken serialized = future .get ();
216
- assertEquals (authentication , serialized .getAuthentication ());
242
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
217
243
}
218
244
219
245
PlainActionFuture <Tuple <UserToken , String >> newTokenFuture = new PlainActionFuture <>();
@@ -242,8 +268,8 @@ private void rotateKeys(TokenService tokenService) {
242
268
}
243
269
244
270
public void testKeyExchange () throws Exception {
245
- TokenService tokenService =
246
- new TokenService (tokenServiceEnabledSettings , systemUTC (), client , lifecycleService , clusterService );
271
+ assumeFalse ( "internally managed keys do not work in a mixed cluster" , mixedCluster );
272
+ TokenService tokenService = new TokenService (tokenServiceEnabledSettings , systemUTC (), client , lifecycleService , clusterService );
247
273
int numRotations = 0 ;randomIntBetween (1 , 5 );
248
274
for (int i = 0 ; i < numRotations ; i ++) {
249
275
rotateKeys (tokenService );
@@ -264,7 +290,7 @@ public void testKeyExchange() throws Exception {
264
290
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
265
291
otherTokenService .getAndValidateToken (requestContext , future );
266
292
UserToken serialized = future .get ();
267
- assertEquals (authentication , serialized .getAuthentication ());
293
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
268
294
}
269
295
270
296
rotateKeys (tokenService );
@@ -275,13 +301,13 @@ public void testKeyExchange() throws Exception {
275
301
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
276
302
otherTokenService .getAndValidateToken (requestContext , future );
277
303
UserToken serialized = future .get ();
278
- assertEquals (authentication , serialized .getAuthentication ());
304
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
279
305
}
280
306
}
281
307
282
308
public void testPruneKeys () throws Exception {
283
- TokenService tokenService =
284
- new TokenService (tokenServiceEnabledSettings , systemUTC (), client , lifecycleService , clusterService );
309
+ assumeFalse ( "internally managed keys do not work in a mixed cluster" , mixedCluster );
310
+ TokenService tokenService = new TokenService (tokenServiceEnabledSettings , systemUTC (), client , lifecycleService , clusterService );
285
311
Authentication authentication = new Authentication (new User ("joe" , "admin" ), new RealmRef ("native_realm" , "native" , "node1" ), null );
286
312
PlainActionFuture <Tuple <UserToken , String >> tokenFuture = new PlainActionFuture <>();
287
313
tokenService .createUserToken (authentication , authentication , tokenFuture , Collections .emptyMap ());
@@ -296,7 +322,7 @@ public void testPruneKeys() throws Exception {
296
322
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
297
323
tokenService .getAndValidateToken (requestContext , future );
298
324
UserToken serialized = future .get ();
299
- assertEquals (authentication , serialized .getAuthentication ());
325
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
300
326
}
301
327
TokenMetaData metaData = tokenService .pruneKeys (randomIntBetween (0 , 100 ));
302
328
tokenService .refreshMetaData (metaData );
@@ -310,7 +336,7 @@ public void testPruneKeys() throws Exception {
310
336
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
311
337
tokenService .getAndValidateToken (requestContext , future );
312
338
UserToken serialized = future .get ();
313
- assertEquals (authentication , serialized .getAuthentication ());
339
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
314
340
}
315
341
316
342
PlainActionFuture <Tuple <UserToken , String >> newTokenFuture = new PlainActionFuture <>();
@@ -336,7 +362,7 @@ public void testPruneKeys() throws Exception {
336
362
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
337
363
tokenService .getAndValidateToken (requestContext , future );
338
364
UserToken serialized = future .get ();
339
- assertEquals (authentication , serialized .getAuthentication ());
365
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
340
366
}
341
367
342
368
}
@@ -358,7 +384,7 @@ public void testPassphraseWorks() throws Exception {
358
384
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
359
385
tokenService .getAndValidateToken (requestContext , future );
360
386
UserToken serialized = future .get ();
361
- assertEquals (authentication , serialized .getAuthentication ());
387
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
362
388
}
363
389
364
390
try (ThreadContext .StoredContext ignore = requestContext .newStoredContext (true )) {
@@ -459,7 +485,7 @@ public void testTokenExpiry() throws Exception {
459
485
// the clock is still frozen, so the cookie should be valid
460
486
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
461
487
tokenService .getAndValidateToken (requestContext , future );
462
- assertEquals (authentication , future .get ().getAuthentication ());
488
+ assertAuthenticationEquals (authentication , future .get ().getAuthentication ());
463
489
}
464
490
465
491
final TimeValue defaultExpiration = TokenService .TOKEN_EXPIRATION .get (Settings .EMPTY );
@@ -469,7 +495,7 @@ public void testTokenExpiry() throws Exception {
469
495
clock .fastForwardSeconds (fastForwardAmount );
470
496
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
471
497
tokenService .getAndValidateToken (requestContext , future );
472
- assertEquals (authentication , future .get ().getAuthentication ());
498
+ assertAuthenticationEquals (authentication , future .get ().getAuthentication ());
473
499
}
474
500
475
501
try (ThreadContext .StoredContext ignore = requestContext .newStoredContext (true )) {
@@ -478,7 +504,7 @@ public void testTokenExpiry() throws Exception {
478
504
clock .rewind (TimeValue .timeValueNanos (clock .instant ().getNano ())); // trim off nanoseconds since don't store them in the index
479
505
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
480
506
tokenService .getAndValidateToken (requestContext , future );
481
- assertEquals (authentication , future .get ().getAuthentication ());
507
+ assertAuthenticationEquals (authentication , future .get ().getAuthentication ());
482
508
}
483
509
484
510
try (ThreadContext .StoredContext ignore = requestContext .newStoredContext (true )) {
@@ -574,7 +600,7 @@ public void testIndexNotAvailable() throws Exception {
574
600
PlainActionFuture <UserToken > future = new PlainActionFuture <>();
575
601
tokenService .getAndValidateToken (requestContext , future );
576
602
UserToken serialized = future .get ();
577
- assertEquals (authentication , serialized .getAuthentication ());
603
+ assertAuthenticationEquals (authentication , serialized .getAuthentication ());
578
604
579
605
when (lifecycleService .isSecurityIndexAvailable ()).thenReturn (false );
580
606
when (lifecycleService .isSecurityIndexExisting ()).thenReturn (true );
@@ -606,6 +632,7 @@ public void testDecodePre6xToken() throws GeneralSecurityException, ExecutionExc
606
632
assertWarnings ("[xpack.security.authc.token.passphrase] setting was deprecated in Elasticsearch and will be removed in a future" +
607
633
" release! See the breaking changes documentation for the next major version." );
608
634
}
635
+
609
636
public void testGetAuthenticationWorksWithExpiredToken () throws Exception {
610
637
TokenService tokenService =
611
638
new TokenService (tokenServiceEnabledSettings , Clock .systemUTC (), client , lifecycleService , clusterService );
@@ -616,7 +643,7 @@ public void testGetAuthenticationWorksWithExpiredToken() throws Exception {
616
643
PlainActionFuture <Tuple <Authentication , Map <String , Object >>> authFuture = new PlainActionFuture <>();
617
644
tokenService .getAuthenticationAndMetaData (userTokenString , authFuture );
618
645
Authentication retrievedAuth = authFuture .actionGet ().v1 ();
619
- assertEquals (authentication , retrievedAuth );
646
+ assertAuthenticationEquals (authentication , retrievedAuth );
620
647
}
621
648
622
649
private void mockGetTokenFromId (UserToken userToken ) {
@@ -643,4 +670,16 @@ public static void mockGetTokenFromId(UserToken userToken, Client client) {
643
670
return Void .TYPE ;
644
671
}).when (client ).get (any (GetRequest .class ), any (ActionListener .class ));
645
672
}
673
+
674
+ private void assertAuthenticationEquals (Authentication expected , Authentication actual ) {
675
+ if (mixedCluster ) {
676
+ assertNotNull (expected );
677
+ assertNotNull (actual );
678
+ assertEquals (expected .getUser (), actual .getUser ());
679
+ assertEquals (expected .getAuthenticatedBy (), actual .getAuthenticatedBy ());
680
+ assertEquals (expected .getLookedUpBy (), actual .getLookedUpBy ());
681
+ } else {
682
+ assertEquals (expected , actual );
683
+ }
684
+ }
646
685
}
0 commit comments