Skip to content

Commit 98aa7e4

Browse files
committed
Add Project Service Account Auth
1 parent 1e7c6ab commit 98aa7e4

31 files changed

+211
-123
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/SecurityExtension.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.elasticsearch.watcher.ResourceWatcherService;
1717
import org.elasticsearch.xpack.core.security.authc.AuthenticationFailureHandler;
1818
import org.elasticsearch.xpack.core.security.authc.Realm;
19+
import org.elasticsearch.xpack.core.security.authc.service.ServiceAccountTokenStore;
1920
import org.elasticsearch.xpack.core.security.authc.support.UserRoleMapper;
2021
import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine;
2122
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
@@ -114,6 +115,10 @@ default List<BiConsumer<Set<String>, ActionListener<RoleRetrievalResult>>> getRo
114115
return Collections.emptyList();
115116
}
116117

118+
default ServiceAccountTokenStore getServiceAccountTokenStore(SecurityComponents components) {
119+
return null;
120+
}
121+
117122
/**
118123
* Returns a authorization engine for authorizing requests, or null to use the default authorization mechanism.
119124
*

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/service/TokenInfo.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ public int compareTo(TokenInfo o) {
105105

106106
public enum TokenSource {
107107
INDEX,
108-
FILE;
108+
FILE,
109+
EXTENSION
109110
}
110111
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* 2.0.
66
*/
77

8-
package org.elasticsearch.xpack.security.authc.service;
8+
package org.elasticsearch.xpack.core.security.authc.service;
99

1010
import org.apache.logging.log4j.util.Strings;
1111
import org.elasticsearch.common.io.stream.StreamInput;
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* 2.0.
66
*/
77

8-
package org.elasticsearch.xpack.security.authc.service;
8+
package org.elasticsearch.xpack.core.security.authc.service;
99

1010
import org.apache.logging.log4j.LogManager;
1111
import org.apache.logging.log4j.Logger;
@@ -14,9 +14,9 @@
1414
import org.elasticsearch.common.settings.SecureString;
1515
import org.elasticsearch.core.CharArrays;
1616
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
17+
import org.elasticsearch.xpack.core.security.authc.service.ServiceAccount.ServiceAccountId;
1718
import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken;
1819
import org.elasticsearch.xpack.core.security.support.Validation;
19-
import org.elasticsearch.xpack.security.authc.service.ServiceAccount.ServiceAccountId;
2020

2121
import java.io.ByteArrayInputStream;
2222
import java.io.ByteArrayOutputStream;
@@ -51,7 +51,6 @@ public class ServiceAccountToken implements AuthenticationToken, Closeable {
5151
private final ServiceAccountTokenId tokenId;
5252
private final SecureString secret;
5353

54-
// pkg private for testing
5554
ServiceAccountToken(ServiceAccountId accountId, String tokenName, SecureString secret) {
5655
tokenId = new ServiceAccountTokenId(accountId, tokenName);
5756
this.secret = Objects.requireNonNull(secret, "service account token secret cannot be null");
Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* 2.0.
66
*/
77

8-
package org.elasticsearch.xpack.security.authc.service;
8+
package org.elasticsearch.xpack.core.security.authc.service;
99

1010
import org.elasticsearch.action.ActionListener;
1111
import org.elasticsearch.xpack.core.security.action.service.TokenInfo.TokenSource;
@@ -21,12 +21,24 @@ public interface ServiceAccountTokenStore {
2121
void authenticate(ServiceAccountToken token, ActionListener<StoreAuthenticationResult> listener);
2222

2323
class StoreAuthenticationResult {
24-
private final boolean success;
2524
private final TokenSource tokenSource;
25+
private final boolean success;
2626

27-
public StoreAuthenticationResult(boolean success, TokenSource tokenSource) {
28-
this.success = success;
27+
private StoreAuthenticationResult(TokenSource tokenSource, boolean success) {
2928
this.tokenSource = tokenSource;
29+
this.success = success;
30+
}
31+
32+
public static StoreAuthenticationResult successful(TokenSource tokenSource) {
33+
return new StoreAuthenticationResult(tokenSource, true);
34+
}
35+
36+
public static StoreAuthenticationResult failed(TokenSource tokenSource) {
37+
return new StoreAuthenticationResult(tokenSource, false);
38+
}
39+
40+
public static StoreAuthenticationResult fromBooleanResult(TokenSource tokenSource, boolean result) {
41+
return result ? successful(tokenSource) : failed(tokenSource);
3042
}
3143

3244
public boolean isSuccess() {
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
* 2.0.
66
*/
77

8-
package org.elasticsearch.xpack.security.authc.service;
8+
package org.elasticsearch.xpack.core.security.authc.service;
99

1010
import org.elasticsearch.common.settings.SecureString;
1111
import org.elasticsearch.test.ESTestCase;
12+
import org.elasticsearch.xpack.core.security.authc.service.ServiceAccount.ServiceAccountId;
1213
import org.elasticsearch.xpack.core.security.support.Validation;
1314
import org.elasticsearch.xpack.core.security.support.ValidationTests;
14-
import org.elasticsearch.xpack.security.authc.service.ServiceAccount.ServiceAccountId;
1515

1616
import java.io.IOException;
1717

x-pack/plugin/security/src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
exports org.elasticsearch.xpack.security.rest.action.apikey to org.elasticsearch.internal.security;
7575
exports org.elasticsearch.xpack.security.support to org.elasticsearch.internal.security;
7676
exports org.elasticsearch.xpack.security.authz.store to org.elasticsearch.internal.security;
77+
exports org.elasticsearch.xpack.security.authc.service;
7778

7879
provides org.elasticsearch.index.SlowLogFieldProvider with org.elasticsearch.xpack.security.slowlog.SecuritySlowLogFieldProvider;
7980

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
209209
import org.elasticsearch.xpack.core.security.authc.RealmSettings;
210210
import org.elasticsearch.xpack.core.security.authc.Subject;
211+
import org.elasticsearch.xpack.core.security.authc.service.ServiceAccountTokenStore;
211212
import org.elasticsearch.xpack.core.security.authc.support.UserRoleMapper;
212213
import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken;
213214
import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine;
@@ -310,6 +311,7 @@
310311
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
311312
import org.elasticsearch.xpack.security.authc.jwt.JwtRealm;
312313
import org.elasticsearch.xpack.security.authc.service.CachingServiceAccountTokenStore;
314+
import org.elasticsearch.xpack.security.authc.service.CompositeServiceAccountTokenStore;
313315
import org.elasticsearch.xpack.security.authc.service.FileServiceAccountTokenStore;
314316
import org.elasticsearch.xpack.security.authc.service.IndexServiceAccountTokenStore;
315317
import org.elasticsearch.xpack.security.authc.service.ServiceAccountService;
@@ -915,12 +917,53 @@ Collection<Object> createComponents(
915917
this.realms.set(realms);
916918

917919
systemIndices.getMainIndexManager().addStateListener(nativeRoleMappingStore::onSecurityIndexStateChange);
918-
919920
final CacheInvalidatorRegistry cacheInvalidatorRegistry = new CacheInvalidatorRegistry();
920-
cacheInvalidatorRegistry.registerAlias("service", Set.of("file_service_account_token", "index_service_account_token"));
921921
components.add(cacheInvalidatorRegistry);
922-
systemIndices.getMainIndexManager().addStateListener(cacheInvalidatorRegistry::onSecurityIndexStateChange);
923922

923+
final IndexServiceAccountTokenStore indexServiceAccountTokenStore = new IndexServiceAccountTokenStore(
924+
settings,
925+
threadPool,
926+
getClock(),
927+
client,
928+
systemIndices.getMainIndexManager(),
929+
clusterService,
930+
cacheInvalidatorRegistry
931+
);
932+
components.add(indexServiceAccountTokenStore);
933+
934+
final FileServiceAccountTokenStore fileServiceAccountTokenStore = new FileServiceAccountTokenStore(
935+
environment,
936+
resourceWatcherService,
937+
threadPool,
938+
clusterService,
939+
cacheInvalidatorRegistry
940+
);
941+
components.add(fileServiceAccountTokenStore);
942+
cacheInvalidatorRegistry.registerAlias("service", Set.of("file_service_account_token", "index_service_account_token"));
943+
944+
List<ServiceAccountTokenStore> extensionTokenStores = securityExtensions.stream()
945+
.map(extension -> extension.getServiceAccountTokenStore(extensionComponents))
946+
.toList();
947+
948+
ServiceAccountService serviceAccountService;
949+
950+
if (extensionTokenStores.isEmpty()) {
951+
serviceAccountService = new ServiceAccountService(client, fileServiceAccountTokenStore, indexServiceAccountTokenStore);
952+
} else {
953+
// Completely handover service account token management to the extension if provided, this will disable the index managed
954+
// service account tokens managed through the service account token API
955+
logger.debug("Service account authentication handled by extension, disabling file and index token stores");
956+
components.addAll(extensionTokenStores);
957+
serviceAccountService = new ServiceAccountService(
958+
client,
959+
new CompositeServiceAccountTokenStore(extensionTokenStores, client.threadPool().getThreadContext())
960+
);
961+
// TODO Should this also register with the cacheInvalidatorRegistry?
962+
}
963+
964+
components.add(serviceAccountService);
965+
966+
systemIndices.getMainIndexManager().addStateListener(cacheInvalidatorRegistry::onSecurityIndexStateChange);
924967
final NativePrivilegeStore privilegeStore = new NativePrivilegeStore(
925968
settings,
926969
client,
@@ -1004,33 +1047,6 @@ Collection<Object> createComponents(
10041047
);
10051048
components.add(apiKeyService);
10061049

1007-
final IndexServiceAccountTokenStore indexServiceAccountTokenStore = new IndexServiceAccountTokenStore(
1008-
settings,
1009-
threadPool,
1010-
getClock(),
1011-
client,
1012-
systemIndices.getMainIndexManager(),
1013-
clusterService,
1014-
cacheInvalidatorRegistry
1015-
);
1016-
components.add(indexServiceAccountTokenStore);
1017-
1018-
final FileServiceAccountTokenStore fileServiceAccountTokenStore = new FileServiceAccountTokenStore(
1019-
environment,
1020-
resourceWatcherService,
1021-
threadPool,
1022-
clusterService,
1023-
cacheInvalidatorRegistry
1024-
);
1025-
components.add(fileServiceAccountTokenStore);
1026-
1027-
final ServiceAccountService serviceAccountService = new ServiceAccountService(
1028-
client,
1029-
fileServiceAccountTokenStore,
1030-
indexServiceAccountTokenStore
1031-
);
1032-
components.add(serviceAccountService);
1033-
10341050
final RoleProviders roleProviders = new RoleProviders(
10351051
reservedRolesStore,
10361052
fileRolesStore.get(),

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/service/TransportGetServiceAccountAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import org.elasticsearch.xpack.core.security.action.service.GetServiceAccountRequest;
2020
import org.elasticsearch.xpack.core.security.action.service.GetServiceAccountResponse;
2121
import org.elasticsearch.xpack.core.security.action.service.ServiceAccountInfo;
22-
import org.elasticsearch.xpack.security.authc.service.ServiceAccount;
22+
import org.elasticsearch.xpack.core.security.authc.service.ServiceAccount;
2323
import org.elasticsearch.xpack.security.authc.service.ServiceAccountService;
2424

2525
import java.util.function.Predicate;

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/service/TransportGetServiceAccountNodesCredentialsAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
import org.elasticsearch.xpack.core.security.action.service.GetServiceAccountCredentialsNodesResponse;
2222
import org.elasticsearch.xpack.core.security.action.service.GetServiceAccountNodesCredentialsAction;
2323
import org.elasticsearch.xpack.core.security.action.service.TokenInfo;
24+
import org.elasticsearch.xpack.core.security.authc.service.ServiceAccount.ServiceAccountId;
2425
import org.elasticsearch.xpack.security.authc.service.FileServiceAccountTokenStore;
25-
import org.elasticsearch.xpack.security.authc.service.ServiceAccount.ServiceAccountId;
2626

2727
import java.io.IOException;
2828
import java.util.List;

0 commit comments

Comments
 (0)