|
@@ -75,7 +75,6 @@ import org.elasticsearch.xpack.core.security.authc.Authentication;
|
|
|
import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef;
|
|
|
import org.elasticsearch.xpack.core.security.authc.AuthenticationTestHelper;
|
|
|
import org.elasticsearch.xpack.core.security.authc.AuthenticationTests;
|
|
|
-import org.elasticsearch.xpack.core.security.authc.TokenMetadata;
|
|
|
import org.elasticsearch.xpack.core.security.authc.support.TokensInvalidationResult;
|
|
|
import org.elasticsearch.xpack.core.security.user.User;
|
|
|
import org.elasticsearch.xpack.core.watcher.watch.ClockMock;
|
|
@@ -299,209 +298,6 @@ public class TokenServiceTests extends ESTestCase {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void testRotateKey() throws Exception {
|
|
|
- TokenService tokenService = createTokenService(tokenServiceEnabledSettings, systemUTC());
|
|
|
- // This test only makes sense in mixed clusters with pre v7.2.0 nodes where the Key is actually used
|
|
|
- if (null == oldNode) {
|
|
|
- oldNode = addAnotherDataNodeWithVersion(this.clusterService, randomFrom(Version.V_7_0_0, Version.V_7_1_0));
|
|
|
- }
|
|
|
- Authentication authentication = AuthenticationTestHelper.builder()
|
|
|
- .user(new User("joe", "admin"))
|
|
|
- .realmRef(new RealmRef("native_realm", "native", "node1"))
|
|
|
- .build(false);
|
|
|
- PlainActionFuture<TokenService.CreateTokenResult> tokenFuture = new PlainActionFuture<>();
|
|
|
- final String userTokenId = UUIDs.randomBase64UUID();
|
|
|
- final String refreshToken = UUIDs.randomBase64UUID();
|
|
|
- tokenService.createOAuth2Tokens(userTokenId, refreshToken, authentication, authentication, Collections.emptyMap(), tokenFuture);
|
|
|
- final String accessToken = tokenFuture.get().getAccessToken();
|
|
|
- assertNotNull(accessToken);
|
|
|
- mockGetTokenFromId(tokenService, userTokenId, authentication, false);
|
|
|
-
|
|
|
- ThreadContext requestContext = new ThreadContext(Settings.EMPTY);
|
|
|
- storeTokenHeader(requestContext, accessToken);
|
|
|
-
|
|
|
- try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
|
|
|
- PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
|
|
- final SecureString bearerToken = Authenticator.extractBearerTokenFromHeader(requestContext);
|
|
|
- tokenService.tryAuthenticateToken(bearerToken, future);
|
|
|
- UserToken serialized = future.get();
|
|
|
- assertAuthentication(authentication, serialized.getAuthentication());
|
|
|
- }
|
|
|
- rotateKeys(tokenService);
|
|
|
-
|
|
|
- try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
|
|
|
- PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
|
|
- final SecureString bearerToken = Authenticator.extractBearerTokenFromHeader(requestContext);
|
|
|
- tokenService.tryAuthenticateToken(bearerToken, future);
|
|
|
- UserToken serialized = future.get();
|
|
|
- assertAuthentication(authentication, serialized.getAuthentication());
|
|
|
- }
|
|
|
-
|
|
|
- PlainActionFuture<TokenService.CreateTokenResult> newTokenFuture = new PlainActionFuture<>();
|
|
|
- final String newUserTokenId = UUIDs.randomBase64UUID();
|
|
|
- final String newRefreshToken = UUIDs.randomBase64UUID();
|
|
|
- tokenService.createOAuth2Tokens(
|
|
|
- newUserTokenId,
|
|
|
- newRefreshToken,
|
|
|
- authentication,
|
|
|
- authentication,
|
|
|
- Collections.emptyMap(),
|
|
|
- newTokenFuture
|
|
|
- );
|
|
|
- final String newAccessToken = newTokenFuture.get().getAccessToken();
|
|
|
- assertNotNull(newAccessToken);
|
|
|
- assertNotEquals(newAccessToken, accessToken);
|
|
|
-
|
|
|
- requestContext = new ThreadContext(Settings.EMPTY);
|
|
|
- storeTokenHeader(requestContext, newAccessToken);
|
|
|
- mockGetTokenFromId(tokenService, newUserTokenId, authentication, false);
|
|
|
-
|
|
|
- try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
|
|
|
- PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
|
|
- final SecureString bearerToken = Authenticator.extractBearerTokenFromHeader(requestContext);
|
|
|
- tokenService.tryAuthenticateToken(bearerToken, future);
|
|
|
- UserToken serialized = future.get();
|
|
|
- assertAuthentication(authentication, serialized.getAuthentication());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void rotateKeys(TokenService tokenService) {
|
|
|
- TokenMetadata tokenMetadata = tokenService.generateSpareKey();
|
|
|
- tokenService.refreshMetadata(tokenMetadata);
|
|
|
- tokenMetadata = tokenService.rotateToSpareKey();
|
|
|
- tokenService.refreshMetadata(tokenMetadata);
|
|
|
- }
|
|
|
-
|
|
|
- public void testKeyExchange() throws Exception {
|
|
|
- TokenService tokenService = createTokenService(tokenServiceEnabledSettings, systemUTC());
|
|
|
- // This test only makes sense in mixed clusters with pre v7.2.0 nodes where the Key is actually used
|
|
|
- if (null == oldNode) {
|
|
|
- oldNode = addAnotherDataNodeWithVersion(this.clusterService, randomFrom(Version.V_7_0_0, Version.V_7_1_0));
|
|
|
- }
|
|
|
- int numRotations = randomIntBetween(1, 5);
|
|
|
- for (int i = 0; i < numRotations; i++) {
|
|
|
- rotateKeys(tokenService);
|
|
|
- }
|
|
|
- TokenService otherTokenService = createTokenService(tokenServiceEnabledSettings, systemUTC());
|
|
|
- otherTokenService.refreshMetadata(tokenService.getTokenMetadata());
|
|
|
- Authentication authentication = AuthenticationTestHelper.builder()
|
|
|
- .user(new User("joe", "admin"))
|
|
|
- .realmRef(new RealmRef("native_realm", "native", "node1"))
|
|
|
- .build(false);
|
|
|
- PlainActionFuture<TokenService.CreateTokenResult> tokenFuture = new PlainActionFuture<>();
|
|
|
- final String userTokenId = UUIDs.randomBase64UUID();
|
|
|
- final String refreshToken = UUIDs.randomBase64UUID();
|
|
|
- tokenService.createOAuth2Tokens(userTokenId, refreshToken, authentication, authentication, Collections.emptyMap(), tokenFuture);
|
|
|
- final String accessToken = tokenFuture.get().getAccessToken();
|
|
|
- assertNotNull(accessToken);
|
|
|
- mockGetTokenFromId(tokenService, userTokenId, authentication, false);
|
|
|
-
|
|
|
- ThreadContext requestContext = new ThreadContext(Settings.EMPTY);
|
|
|
- storeTokenHeader(requestContext, accessToken);
|
|
|
- try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
|
|
|
- PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
|
|
- final SecureString bearerToken = Authenticator.extractBearerTokenFromHeader(requestContext);
|
|
|
- otherTokenService.tryAuthenticateToken(bearerToken, future);
|
|
|
- UserToken serialized = future.get();
|
|
|
- assertAuthentication(serialized.getAuthentication(), authentication);
|
|
|
- }
|
|
|
-
|
|
|
- rotateKeys(tokenService);
|
|
|
-
|
|
|
- otherTokenService.refreshMetadata(tokenService.getTokenMetadata());
|
|
|
-
|
|
|
- try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
|
|
|
- PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
|
|
- final SecureString bearerToken = Authenticator.extractBearerTokenFromHeader(requestContext);
|
|
|
- otherTokenService.tryAuthenticateToken(bearerToken, future);
|
|
|
- UserToken serialized = future.get();
|
|
|
- assertAuthentication(serialized.getAuthentication(), authentication);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void testPruneKeys() throws Exception {
|
|
|
- TokenService tokenService = createTokenService(tokenServiceEnabledSettings, systemUTC());
|
|
|
- // This test only makes sense in mixed clusters with pre v7.2.0 nodes where the Key is actually used
|
|
|
- if (null == oldNode) {
|
|
|
- oldNode = addAnotherDataNodeWithVersion(this.clusterService, randomFrom(Version.V_7_0_0, Version.V_7_1_0));
|
|
|
- }
|
|
|
- Authentication authentication = AuthenticationTestHelper.builder()
|
|
|
- .user(new User("joe", "admin"))
|
|
|
- .realmRef(new RealmRef("native_realm", "native", "node1"))
|
|
|
- .build(false);
|
|
|
- PlainActionFuture<TokenService.CreateTokenResult> tokenFuture = new PlainActionFuture<>();
|
|
|
- final String userTokenId = UUIDs.randomBase64UUID();
|
|
|
- final String refreshToken = UUIDs.randomBase64UUID();
|
|
|
- tokenService.createOAuth2Tokens(userTokenId, refreshToken, authentication, authentication, Collections.emptyMap(), tokenFuture);
|
|
|
- final String accessToken = tokenFuture.get().getAccessToken();
|
|
|
- assertNotNull(accessToken);
|
|
|
- mockGetTokenFromId(tokenService, userTokenId, authentication, false);
|
|
|
-
|
|
|
- ThreadContext requestContext = new ThreadContext(Settings.EMPTY);
|
|
|
- storeTokenHeader(requestContext, accessToken);
|
|
|
-
|
|
|
- try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
|
|
|
- PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
|
|
- final SecureString bearerToken = Authenticator.extractBearerTokenFromHeader(requestContext);
|
|
|
- tokenService.tryAuthenticateToken(bearerToken, future);
|
|
|
- UserToken serialized = future.get();
|
|
|
- assertAuthentication(authentication, serialized.getAuthentication());
|
|
|
- }
|
|
|
- TokenMetadata metadata = tokenService.pruneKeys(randomIntBetween(0, 100));
|
|
|
- tokenService.refreshMetadata(metadata);
|
|
|
-
|
|
|
- int numIterations = scaledRandomIntBetween(1, 5);
|
|
|
- for (int i = 0; i < numIterations; i++) {
|
|
|
- rotateKeys(tokenService);
|
|
|
- }
|
|
|
-
|
|
|
- try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
|
|
|
- PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
|
|
- final SecureString bearerToken = Authenticator.extractBearerTokenFromHeader(requestContext);
|
|
|
- tokenService.tryAuthenticateToken(bearerToken, future);
|
|
|
- UserToken serialized = future.get();
|
|
|
- assertAuthentication(authentication, serialized.getAuthentication());
|
|
|
- }
|
|
|
-
|
|
|
- PlainActionFuture<TokenService.CreateTokenResult> newTokenFuture = new PlainActionFuture<>();
|
|
|
- final String newUserTokenId = UUIDs.randomBase64UUID();
|
|
|
- final String newRefreshToken = UUIDs.randomBase64UUID();
|
|
|
- tokenService.createOAuth2Tokens(
|
|
|
- newUserTokenId,
|
|
|
- newRefreshToken,
|
|
|
- authentication,
|
|
|
- authentication,
|
|
|
- Collections.emptyMap(),
|
|
|
- newTokenFuture
|
|
|
- );
|
|
|
- final String newAccessToken = newTokenFuture.get().getAccessToken();
|
|
|
- assertNotNull(newAccessToken);
|
|
|
- assertNotEquals(newAccessToken, accessToken);
|
|
|
-
|
|
|
- metadata = tokenService.pruneKeys(1);
|
|
|
- tokenService.refreshMetadata(metadata);
|
|
|
-
|
|
|
- try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
|
|
|
- PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
|
|
- final SecureString bearerToken = Authenticator.extractBearerTokenFromHeader(requestContext);
|
|
|
- tokenService.tryAuthenticateToken(bearerToken, future);
|
|
|
- UserToken serialized = future.get();
|
|
|
- assertNull(serialized);
|
|
|
- }
|
|
|
-
|
|
|
- requestContext = new ThreadContext(Settings.EMPTY);
|
|
|
- storeTokenHeader(requestContext, newAccessToken);
|
|
|
- mockGetTokenFromId(tokenService, newUserTokenId, authentication, false);
|
|
|
- try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
|
|
|
- PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
|
|
- final SecureString bearerToken = Authenticator.extractBearerTokenFromHeader(requestContext);
|
|
|
- tokenService.tryAuthenticateToken(bearerToken, future);
|
|
|
- UserToken serialized = future.get();
|
|
|
- assertAuthentication(authentication, serialized.getAuthentication());
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
public void testPassphraseWorks() throws Exception {
|
|
|
TokenService tokenService = createTokenService(tokenServiceEnabledSettings, systemUTC());
|
|
|
// This test only makes sense in mixed clusters with pre v7.1.0 nodes where the Key is actually used
|