Skip to content

Commit e244a3b

Browse files
authored
Check authentication type using enum instead of string (#54145)
Avoid string comparison when we can use safter enums. This refactor is a follow up for #52178. Resolves: #52511
1 parent e8e8b16 commit e244a3b

File tree

7 files changed

+35
-21
lines changed

7 files changed

+35
-21
lines changed

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

+4
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ public RealmRef getLookedUpBy() {
7777
return lookedUpBy;
7878
}
7979

80+
/**
81+
* Get the realm where the effective user comes from.
82+
* The effective user is the es-security-runas-user if present or the authenticated user.
83+
*/
8084
public RealmRef getSourceRealm() {
8185
return lookedUpBy == null ? authenticatedBy : lookedUpBy;
8286
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ManageOwnApiKeyClusterPrivilege.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.xpack.core.security.action.GetApiKeyRequest;
1515
import org.elasticsearch.xpack.core.security.action.InvalidateApiKeyRequest;
1616
import org.elasticsearch.xpack.core.security.authc.Authentication;
17+
import org.elasticsearch.xpack.core.security.authc.Authentication.AuthenticationType;
1718
import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission;
1819
import org.elasticsearch.xpack.core.security.support.Automatons;
1920

@@ -23,7 +24,6 @@
2324
public class ManageOwnApiKeyClusterPrivilege implements NamedClusterPrivilege {
2425
public static final ManageOwnApiKeyClusterPrivilege INSTANCE = new ManageOwnApiKeyClusterPrivilege();
2526
private static final String PRIVILEGE_NAME = "manage_own_api_key";
26-
private static final String API_KEY_REALM_TYPE = "_es_api_key";
2727
private static final String API_KEY_ID_KEY = "_security_api_key_id";
2828

2929
private ManageOwnApiKeyClusterPrivilege() {
@@ -78,7 +78,7 @@ private boolean checkIfUserIsOwnerOfApiKeys(Authentication authentication, Strin
7878
* TODO bizybot we need to think on how we can propagate appropriate error message to the end user when username, realm name
7979
* is missing. This is similar to the problem of propagating right error messages in case of access denied.
8080
*/
81-
if (authentication.getSourceRealm().getType().equals(API_KEY_REALM_TYPE)) {
81+
if (AuthenticationType.API_KEY == authentication.getAuthenticationType()) {
8282
// API key cannot own any other API key so deny access
8383
return false;
8484
} else if (ownedByAuthenticatedUser) {
@@ -93,7 +93,7 @@ private boolean checkIfUserIsOwnerOfApiKeys(Authentication authentication, Strin
9393
}
9494

9595
private boolean isCurrentAuthenticationUsingSameApiKeyIdFromRequest(Authentication authentication, String apiKeyId) {
96-
if (authentication.getSourceRealm().getType().equals(API_KEY_REALM_TYPE)) {
96+
if (AuthenticationType.API_KEY == authentication.getAuthenticationType()) {
9797
// API key id from authentication must match the id from request
9898
final String authenticatedApiKeyId = (String) authentication.getMetadata().get(API_KEY_ID_KEY);
9999
if (Strings.hasText(apiKeyId)) {

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/ManageOwnApiKeyClusterPrivilegeTests.java

+15-9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.xpack.core.security.action.GetApiKeyRequest;
1414
import org.elasticsearch.xpack.core.security.action.InvalidateApiKeyRequest;
1515
import org.elasticsearch.xpack.core.security.authc.Authentication;
16+
import org.elasticsearch.xpack.core.security.authc.Authentication.AuthenticationType;
1617
import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission;
1718
import org.elasticsearch.xpack.core.security.user.User;
1819

@@ -28,8 +29,8 @@ public void testAuthenticationWithApiKeyAllowsAccessToApiKeyActionsWhenItIsOwner
2829
ManageOwnApiKeyClusterPrivilege.INSTANCE.buildPermission(ClusterPermission.builder()).build();
2930

3031
final String apiKeyId = randomAlphaOfLengthBetween(4, 7);
31-
final Authentication authentication = createMockAuthentication("joe","_es_api_key", "_es_api_key",
32-
Map.of("_security_api_key_id", apiKeyId));
32+
final Authentication authentication = createMockAuthentication("joe","_es_api_key",
33+
AuthenticationType.API_KEY, Map.of("_security_api_key_id", apiKeyId));
3334
final TransportRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyId(apiKeyId, randomBoolean());
3435
final TransportRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyId(apiKeyId, randomBoolean());
3536

@@ -43,8 +44,8 @@ public void testAuthenticationWithApiKeyDeniesAccessToApiKeyActionsWhenItIsNotOw
4344
ManageOwnApiKeyClusterPrivilege.INSTANCE.buildPermission(ClusterPermission.builder()).build();
4445

4546
final String apiKeyId = randomAlphaOfLengthBetween(4, 7);
46-
final Authentication authentication = createMockAuthentication("joe","_es_api_key", "_es_api_key",
47-
Map.of("_security_api_key_id", randomAlphaOfLength(7)));
47+
final Authentication authentication = createMockAuthentication("joe","_es_api_key",
48+
AuthenticationType.API_KEY, Map.of("_security_api_key_id", randomAlphaOfLength(7)));
4849
final TransportRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyId(apiKeyId, randomBoolean());
4950
final TransportRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyId(apiKeyId, randomBoolean());
5051

@@ -56,7 +57,8 @@ public void testAuthenticationWithUserAllowsAccessToApiKeyActionsWhenItIsOwner()
5657
final ClusterPermission clusterPermission =
5758
ManageOwnApiKeyClusterPrivilege.INSTANCE.buildPermission(ClusterPermission.builder()).build();
5859

59-
final Authentication authentication = createMockAuthentication("joe","realm1", "native", Map.of());
60+
final Authentication authentication = createMockAuthentication("joe","realm1",
61+
AuthenticationType.REALM, Map.of());
6062
final TransportRequest getApiKeyRequest = GetApiKeyRequest.usingRealmAndUserName("realm1", "joe");
6163
final TransportRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingRealmAndUserName("realm1", "joe");
6264

@@ -69,7 +71,8 @@ public void testAuthenticationWithUserAllowsAccessToApiKeyActionsWhenItIsOwner_W
6971
final ClusterPermission clusterPermission =
7072
ManageOwnApiKeyClusterPrivilege.INSTANCE.buildPermission(ClusterPermission.builder()).build();
7173

72-
final Authentication authentication = createMockAuthentication("joe","realm1", "native", Map.of());
74+
final Authentication authentication = createMockAuthentication("joe","realm1",
75+
AuthenticationType.REALM, Map.of());
7376
final TransportRequest getApiKeyRequest = GetApiKeyRequest.forOwnedApiKeys();
7477
final TransportRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.forOwnedApiKeys();
7578

@@ -82,7 +85,8 @@ public void testAuthenticationWithUserDeniesAccessToApiKeyActionsWhenItIsNotOwne
8285
final ClusterPermission clusterPermission =
8386
ManageOwnApiKeyClusterPrivilege.INSTANCE.buildPermission(ClusterPermission.builder()).build();
8487

85-
final Authentication authentication = createMockAuthentication("joe", "realm1", "native", Map.of());
88+
final Authentication authentication = createMockAuthentication("joe", "realm1",
89+
AuthenticationType.REALM, Map.of());
8690
final TransportRequest getApiKeyRequest = randomFrom(
8791
GetApiKeyRequest.usingRealmAndUserName("realm1", randomAlphaOfLength(7)),
8892
GetApiKeyRequest.usingRealmAndUserName(randomAlphaOfLength(5), "joe"),
@@ -110,14 +114,15 @@ public void testGetAndInvalidateApiKeyWillRespectRunAsUser() {
110114
InvalidateApiKeyRequest.usingRealmAndUserName("realm_b", "user_b"), authentication));
111115
}
112116

113-
private Authentication createMockAuthentication(String username, String realmName, String realmType, Map<String, Object> metadata) {
117+
private Authentication createMockAuthentication(String username, String realmName,
118+
AuthenticationType authenticationType, Map<String, Object> metadata) {
114119
final User user = new User(username);
115120
final Authentication authentication = mock(Authentication.class);
116121
final Authentication.RealmRef authenticatedBy = mock(Authentication.RealmRef.class);
117122
when(authentication.getUser()).thenReturn(user);
118123
when(authentication.getSourceRealm()).thenReturn(authenticatedBy);
124+
when(authentication.getAuthenticationType()).thenReturn(authenticationType);
119125
when(authenticatedBy.getName()).thenReturn(realmName);
120-
when(authenticatedBy.getType()).thenReturn(realmType);
121126
when(authentication.getMetadata()).thenReturn(metadata);
122127
return authentication;
123128
}
@@ -136,6 +141,7 @@ private Authentication createMockRunAsAuthentication(String username, String rea
136141
when(authentication.getAuthenticatedBy()).thenReturn(authenticatedBy);
137142
when(authentication.getSourceRealm()).thenReturn(lookedUpBy);
138143
when(authentication.getMetadata()).thenReturn(Map.of());
144+
when(authentication.getAuthenticationType()).thenReturn(AuthenticationType.REALM);
139145
return authentication;
140146
}
141147
}

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
import static org.elasticsearch.search.SearchService.DEFAULT_KEEPALIVE_SETTING;
103103
import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN;
104104
import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
105+
import static org.elasticsearch.xpack.core.security.authc.Authentication.AuthenticationType;
105106
import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
106107

107108
public class ApiKeyService {
@@ -343,7 +344,7 @@ private void loadApiKeyAndValidateCredentials(ThreadContext ctx, ApiKeyCredentia
343344
* retrieval of role descriptors that are associated with the api key
344345
*/
345346
public void getRoleForApiKey(Authentication authentication, ActionListener<ApiKeyRoleDescriptors> listener) {
346-
if (authentication.getAuthenticationType() != Authentication.AuthenticationType.API_KEY) {
347+
if (authentication.getAuthenticationType() != AuthenticationType.API_KEY) {
347348
throw new IllegalStateException("authentication type must be api key but is " + authentication.getAuthenticationType());
348349
}
349350

@@ -894,7 +895,7 @@ public void getApiKeys(String realmName, String username, String apiKeyName, Str
894895
* @return realm name
895896
*/
896897
public static String getCreatorRealmName(final Authentication authentication) {
897-
if (authentication.getAuthenticatedBy().getType().equals(API_KEY_REALM_TYPE)) {
898+
if (AuthenticationType.API_KEY == authentication.getAuthenticationType()) {
898899
return (String) authentication.getMetadata().get(API_KEY_CREATOR_REALM_NAME);
899900
} else {
900901
return authentication.getSourceRealm().getName();
@@ -909,7 +910,7 @@ public static String getCreatorRealmName(final Authentication authentication) {
909910
* @return realm type
910911
*/
911912
public static String getCreatorRealmType(final Authentication authentication) {
912-
if (authentication.getAuthenticatedBy().getType().equals(API_KEY_REALM_TYPE)) {
913+
if (AuthenticationType.API_KEY == authentication.getAuthenticationType()) {
913914
return (String) authentication.getMetadata().get(API_KEY_CREATOR_REALM_TYPE);
914915
} else {
915916
return authentication.getSourceRealm().getType();

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.elasticsearch.xpack.core.security.action.user.HasPrivilegesRequest;
4343
import org.elasticsearch.xpack.core.security.action.user.HasPrivilegesResponse;
4444
import org.elasticsearch.xpack.core.security.authc.Authentication;
45+
import org.elasticsearch.xpack.core.security.authc.Authentication.AuthenticationType;
4546
import org.elasticsearch.xpack.core.security.authc.AuthenticationFailureHandler;
4647
import org.elasticsearch.xpack.core.security.authc.esnative.ClientReservedRealm;
4748
import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine;
@@ -585,7 +586,7 @@ private ElasticsearchSecurityException denialException(Authentication authentica
585586
authentication.getUser().principal());
586587
}
587588
// check for authentication by API key
588-
if (authentication.getAuthenticatedBy().getType().equals(ApiKeyService.API_KEY_REALM_TYPE)) {
589+
if (AuthenticationType.API_KEY == authentication.getAuthenticationType()) {
589590
final String apiKeyId = (String) authentication.getMetadata().get(ApiKeyService.API_KEY_ID_KEY);
590591
assert apiKeyId != null : "api key id must be present in the metadata";
591592
logger.debug("action [{}] is unauthorized for API key id [{}] of user [{}]", action, apiKeyId, authUser.principal());

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.elasticsearch.xpack.core.security.action.user.HasPrivilegesResponse;
4848
import org.elasticsearch.xpack.core.security.action.user.UserRequest;
4949
import org.elasticsearch.xpack.core.security.authc.Authentication;
50+
import org.elasticsearch.xpack.core.security.authc.Authentication.AuthenticationType;
5051
import org.elasticsearch.xpack.core.security.authc.esnative.NativeRealmSettings;
5152
import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine;
5253
import org.elasticsearch.xpack.core.security.authz.ResolvedIndices;
@@ -179,7 +180,7 @@ boolean checkSameUserPermissions(String action, TransportRequest request, Authen
179180
return sameUsername;
180181
} else if (request instanceof GetApiKeyRequest) {
181182
GetApiKeyRequest getApiKeyRequest = (GetApiKeyRequest) request;
182-
if (authentication.getAuthenticatedBy().getType().equals(ApiKeyService.API_KEY_REALM_TYPE)) {
183+
if (AuthenticationType.API_KEY == authentication.getAuthenticationType()) {
183184
assert authentication.getLookedUpBy() == null : "runAs not supported for api key authentication";
184185
// if authenticated by API key then the request must also contain same API key id
185186
String authenticatedApiKeyId = (String) authentication.getMetadata().get(ApiKeyService.API_KEY_ID_KEY);
@@ -542,8 +543,8 @@ private static boolean checkChangePasswordAction(Authentication authentication)
542543
// Ensure that the user is not authenticated with an access token or an API key.
543544
// Also ensure that the user was authenticated by a realm that we can change a password for. The native realm is an internal realm
544545
// and right now only one can exist in the realm configuration - if this changes we should update this check
545-
final Authentication.AuthenticationType authType = authentication.getAuthenticationType();
546-
return (authType.equals(Authentication.AuthenticationType.REALM)
546+
final AuthenticationType authType = authentication.getAuthenticationType();
547+
return (authType.equals(AuthenticationType.REALM)
547548
&& (ReservedRealm.TYPE.equals(realmType) || NativeRealmSettings.TYPE.equals(realmType)));
548549
}
549550

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/RBACEngineTests.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.elasticsearch.xpack.core.security.action.user.PutUserAction;
3737
import org.elasticsearch.xpack.core.security.action.user.UserRequest;
3838
import org.elasticsearch.xpack.core.security.authc.Authentication;
39+
import org.elasticsearch.xpack.core.security.authc.Authentication.AuthenticationType;
3940
import org.elasticsearch.xpack.core.security.authc.esnative.NativeRealmSettings;
4041
import org.elasticsearch.xpack.core.security.authc.file.FileRealmSettings;
4142
import org.elasticsearch.xpack.core.security.authc.ldap.LdapRealmSettings;
@@ -291,7 +292,7 @@ public void testSameUserPermissionAllowsSelfApiKeyInfoRetrievalWhenAuthenticated
291292
final Authentication.RealmRef authenticatedBy = mock(Authentication.RealmRef.class);
292293
when(authentication.getUser()).thenReturn(user);
293294
when(authentication.getAuthenticatedBy()).thenReturn(authenticatedBy);
294-
when(authenticatedBy.getType()).thenReturn(ApiKeyService.API_KEY_REALM_TYPE);
295+
when(authentication.getAuthenticationType()).thenReturn(AuthenticationType.API_KEY);
295296
when(authentication.getMetadata()).thenReturn(Map.of(ApiKeyService.API_KEY_ID_KEY, apiKeyId));
296297

297298
assertTrue(engine.checkSameUserPermissions(GetApiKeyAction.NAME, request, authentication));
@@ -321,7 +322,7 @@ public void testSameUserPermissionDeniesApiKeyInfoRetrievalWhenLookedupByIsPrese
321322
when(authentication.getUser()).thenReturn(user);
322323
when(authentication.getAuthenticatedBy()).thenReturn(authenticatedBy);
323324
when(authentication.getLookedUpBy()).thenReturn(lookedupBy);
324-
when(authenticatedBy.getType()).thenReturn(ApiKeyService.API_KEY_REALM_TYPE);
325+
when(authentication.getAuthenticationType()).thenReturn(AuthenticationType.API_KEY);
325326
when(authentication.getMetadata()).thenReturn(Map.of(ApiKeyService.API_KEY_ID_KEY, randomAlphaOfLengthBetween(4, 7)));
326327

327328
final AssertionError assertionError = expectThrows(AssertionError.class, () -> engine.checkSameUserPermissions(GetApiKeyAction.NAME,

0 commit comments

Comments
 (0)