From e2deab0f5a8f0fa6d59e96c084da39ce4afb09f5 Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Mon, 17 Jan 2022 13:53:17 +1100 Subject: [PATCH 1/4] Replace superuser role for API keys (#81977) This PR replace superuser role of an API key with the new limited superuser role to prevent write access to system indices. The replacement should only happen to the builtin superuser role. If there is a user-created role that has the exact same definition as the superuser role, it will not be replaced because we consider users are explicitly opt-in for ALL access in this scenario. Relates: #81400 --- .../xpack/security/authc/ApiKeyService.java | 78 +++++++++++++++-- .../authz/store/CompositeRolesStore.java | 6 +- .../security/authc/ApiKeyServiceTests.java | 24 +++++- .../authz/store/CompositeRolesStoreTests.java | 8 +- .../xpack/restart/FullClusterRestartIT.java | 86 +++++++++++++++++++ 5 files changed, 185 insertions(+), 17 deletions(-) diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ApiKeyService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ApiKeyService.java index 7c11aee6d469f..4bea988c44cef 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ApiKeyService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ApiKeyService.java @@ -92,6 +92,8 @@ import org.elasticsearch.xpack.core.security.authc.service.ServiceAccountSettings; import org.elasticsearch.xpack.core.security.authc.support.Hasher; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; +import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; +import org.elasticsearch.xpack.core.security.support.MetadataUtils; import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.security.support.CacheInvalidatorRegistry; import org.elasticsearch.xpack.security.support.FeatureNotEnabledException; @@ -588,11 +590,19 @@ public void getRoleForApiKey(Authentication authentication, ActionListener authnRoleDescriptorsList = parseRoleDescriptors(apiKeyId, authnRoleDescriptors); + final List authnRoleDescriptorsList = parseRoleDescriptors( + apiKeyId, + authnRoleDescriptors, + ApiKeyRoleType.LIMITED_BY + ); listener.onResponse(new ApiKeyRoleDescriptors(apiKeyId, authnRoleDescriptorsList, null)); } else { - final List roleDescriptorList = parseRoleDescriptors(apiKeyId, roleDescriptors); - final List authnRoleDescriptorsList = parseRoleDescriptors(apiKeyId, authnRoleDescriptors); + final List roleDescriptorList = parseRoleDescriptors(apiKeyId, roleDescriptors, ApiKeyRoleType.ASSIGNED); + final List authnRoleDescriptorsList = parseRoleDescriptors( + apiKeyId, + authnRoleDescriptors, + ApiKeyRoleType.LIMITED_BY + ); listener.onResponse(new ApiKeyRoleDescriptors(apiKeyId, roleDescriptorList, authnRoleDescriptorsList)); } } @@ -642,11 +652,15 @@ public List getLimitedByRoleDescriptors() { } } - private List parseRoleDescriptors(final String apiKeyId, final Map roleDescriptors) { - if (roleDescriptors == null) { + private List parseRoleDescriptors( + final String apiKeyId, + final Map roleDescriptorsMap, + ApiKeyRoleType roleType + ) { + if (roleDescriptorsMap == null) { return null; } - return roleDescriptors.entrySet().stream().map(entry -> { + final List roleDescriptors = roleDescriptorsMap.entrySet().stream().map(entry -> { final String name = entry.getKey(); @SuppressWarnings("unchecked") final Map rdMap = (Map) entry.getValue(); @@ -666,9 +680,10 @@ private List parseRoleDescriptors(final String apiKeyId, final M throw new UncheckedIOException(e); } }).collect(Collectors.toList()); + return roleType == ApiKeyRoleType.LIMITED_BY ? maybeReplaceSuperuserRoleDescriptor(apiKeyId, roleDescriptors) : roleDescriptors; } - public List parseRoleDescriptors(final String apiKeyId, BytesReference bytesReference) { + public List parseRoleDescriptors(final String apiKeyId, BytesReference bytesReference, ApiKeyRoleType roleType) { if (bytesReference == null) { return Collections.emptyList(); } @@ -691,7 +706,40 @@ public List parseRoleDescriptors(final String apiKeyId, BytesRef } catch (IOException e) { throw new UncheckedIOException(e); } - return Collections.unmodifiableList(roleDescriptors); + return roleType == ApiKeyRoleType.LIMITED_BY ? maybeReplaceSuperuserRoleDescriptor(apiKeyId, roleDescriptors) : roleDescriptors; + } + + // package private for tests + static final RoleDescriptor LEGACY_SUPERUSER_ROLE_DESCRIPTOR = new RoleDescriptor( + "superuser", + new String[] { "all" }, + new RoleDescriptor.IndicesPrivileges[] { + RoleDescriptor.IndicesPrivileges.builder().indices("*").privileges("all").allowRestrictedIndices(true).build() }, + new RoleDescriptor.ApplicationResourcePrivileges[] { + RoleDescriptor.ApplicationResourcePrivileges.builder().application("*").privileges("*").resources("*").build() }, + null, + new String[] { "*" }, + MetadataUtils.DEFAULT_RESERVED_METADATA, + Collections.emptyMap() + ); + + // This method should only be called to replace the superuser role descriptor for the limited-by roles of an API Key. + // We do not replace assigned roles because they are created explicitly by users. + // Before #82049, it is possible to specify a role descriptor for API keys that is identical to the builtin superuser role + // (including the _reserved metadata field). + private List maybeReplaceSuperuserRoleDescriptor(String apiKeyId, List roleDescriptors) { + // Scan through all the roles because superuser can be one of the roles that a user has. Unlike building the Role object, + // capturing role descriptors does not preempt for superuser. + return roleDescriptors.stream().map(rd -> { + // Since we are only replacing limited-by roles and all limited-by roles are looked up with role providers, + // it is technically possible to just check the name of superuser and the _reserved metadata field. + // But the gain is not much since role resolving is cached and comparing the whole role descriptor is still safer. + if (rd.equals(LEGACY_SUPERUSER_ROLE_DESCRIPTOR)) { + logger.debug("replacing superuser role for API key [{}]", apiKeyId); + return ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR; + } + return rd; + }).toList(); } /** @@ -1709,4 +1757,18 @@ public void invalidateAll() { roleDescriptorsBytesCache.invalidateAll(); } } + + /** + * The type of one set of API key roles. + */ + public enum ApiKeyRoleType { + /** + * Roles directly specified by the creator user on API key creation + */ + ASSIGNED, + /** + * Roles captured for the owner user as the upper bound of the assigned roles + */ + LIMITED_BY; + } } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStore.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStore.java index cd09f312cdb03..e87390347861a 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStore.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStore.java @@ -422,7 +422,11 @@ private void buildAndCacheRoleForApiKey(Authentication authentication, boolean l final Role existing = roleCache.get(roleKey); if (existing == null) { final long invalidationCounter = numInvalidation.get(); - final List roleDescriptors = apiKeyService.parseRoleDescriptors(apiKeyIdAndBytes.v1(), apiKeyIdAndBytes.v2()); + final List roleDescriptors = apiKeyService.parseRoleDescriptors( + apiKeyIdAndBytes.v1(), + apiKeyIdAndBytes.v2(), + limitedBy ? ApiKeyService.ApiKeyRoleType.LIMITED_BY : ApiKeyService.ApiKeyRoleType.ASSIGNED + ); buildThenMaybeCacheRole(roleKey, roleDescriptors, Collections.emptySet(), true, invalidationCounter, roleActionListener); } else { roleActionListener.onResponse(existing); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java index d1595a96c2312..4d9864135e18e 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java @@ -116,6 +116,7 @@ import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS; import static org.elasticsearch.xpack.security.Security.SECURITY_CRYPTO_THREAD_POOL_NAME; import static org.elasticsearch.xpack.security.authc.ApiKeyService.API_KEY_METADATA_KEY; +import static org.elasticsearch.xpack.security.authc.ApiKeyService.LEGACY_SUPERUSER_ROLE_DESCRIPTOR; import static org.hamcrest.Matchers.anEmptyMap; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; @@ -702,11 +703,11 @@ public void testGetApiKeyIdAndRoleBytes() { public void testParseRoleDescriptors() { ApiKeyService service = createApiKeyService(Settings.EMPTY); final String apiKeyId = randomAlphaOfLength(12); - List roleDescriptors = service.parseRoleDescriptors(apiKeyId, null); + List roleDescriptors = service.parseRoleDescriptors(apiKeyId, null, randomApiKeyRoleType()); assertTrue(roleDescriptors.isEmpty()); BytesReference roleBytes = new BytesArray("{\"a role\": {\"cluster\": [\"all\"]}}"); - roleDescriptors = service.parseRoleDescriptors(apiKeyId, roleBytes); + roleDescriptors = service.parseRoleDescriptors(apiKeyId, roleBytes, randomApiKeyRoleType()); assertEquals(1, roleDescriptors.size()); assertEquals("a role", roleDescriptors.get(0).getName()); assertArrayEquals(new String[] { "all" }, roleDescriptors.get(0).getClusterPrivileges()); @@ -720,12 +721,19 @@ public void testParseRoleDescriptors() { + "\"privileges\":[\"*\"],\"resources\":[\"*\"]}],\"run_as\":[\"*\"],\"metadata\":{\"_reserved\":true}," + "\"transient_metadata\":{}}}\n" ); - roleDescriptors = service.parseRoleDescriptors(apiKeyId, roleBytes); + final ApiKeyService.ApiKeyRoleType apiKeyRoleType = randomApiKeyRoleType(); + roleDescriptors = service.parseRoleDescriptors(apiKeyId, roleBytes, apiKeyRoleType); assertEquals(2, roleDescriptors.size()); assertEquals( Set.of("reporting_user", "superuser"), roleDescriptors.stream().map(RoleDescriptor::getName).collect(Collectors.toSet()) ); + assertThat( + roleDescriptors.get(1), + equalTo( + apiKeyRoleType == ApiKeyService.ApiKeyRoleType.LIMITED_BY ? SUPERUSER_ROLE_DESCRIPTOR : LEGACY_SUPERUSER_ROLE_DESCRIPTOR + ) + ); } public void testApiKeyServiceDisabled() throws Exception { @@ -1122,7 +1130,11 @@ public void testApiKeyDocCache() throws IOException, ExecutionException, Interru final BytesReference limitedByRoleDescriptorsBytes = service.getRoleDescriptorsBytesCache() .get(cachedApiKeyDoc.limitedByRoleDescriptorsHash); assertNotNull(limitedByRoleDescriptorsBytes); - final List limitedByRoleDescriptors = service.parseRoleDescriptors(docId, limitedByRoleDescriptorsBytes); + final List limitedByRoleDescriptors = service.parseRoleDescriptors( + docId, + limitedByRoleDescriptorsBytes, + ApiKeyService.ApiKeyRoleType.LIMITED_BY + ); assertEquals(1, limitedByRoleDescriptors.size()); assertEquals(SUPERUSER_ROLE_DESCRIPTOR, limitedByRoleDescriptors.get(0)); if (metadata == null) { @@ -1695,4 +1707,8 @@ private void checkAuthApiKeyMetadata(Object metadata, AuthenticationResult ); } } + + private ApiKeyService.ApiKeyRoleType randomApiKeyRoleType() { + return randomFrom(ApiKeyService.ApiKeyRoleType.values()); + } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java index 4df4270c46c4d..d27fa84ff2c29 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java @@ -1551,8 +1551,8 @@ public void testCacheEntryIsReusedForIdenticalApiKeyRoles() { roleFuture.actionGet(); assertThat(effectiveRoleDescriptors.get(), is(nullValue())); verify(apiKeyService, times(2)).getApiKeyIdAndRoleBytes(eq(authentication), anyBoolean()); - verify(apiKeyService).parseRoleDescriptors("key-id-1", roleBytes); - verify(apiKeyService).parseRoleDescriptors("key-id-1", limitedByRoleBytes); + verify(apiKeyService).parseRoleDescriptors("key-id-1", roleBytes, ApiKeyService.ApiKeyRoleType.ASSIGNED); + verify(apiKeyService).parseRoleDescriptors("key-id-1", limitedByRoleBytes, ApiKeyService.ApiKeyRoleType.LIMITED_BY); // Different API key with the same roles should read from cache authentication = new Authentication( @@ -1576,7 +1576,7 @@ public void testCacheEntryIsReusedForIdenticalApiKeyRoles() { roleFuture.actionGet(); assertThat(effectiveRoleDescriptors.get(), is(nullValue())); verify(apiKeyService, times(2)).getApiKeyIdAndRoleBytes(eq(authentication), anyBoolean()); - verify(apiKeyService, never()).parseRoleDescriptors(eq("key-id-2"), any(BytesReference.class)); + verify(apiKeyService, never()).parseRoleDescriptors(eq("key-id-2"), any(BytesReference.class), any()); // Different API key with the same limitedBy role should read from cache, new role should be built final BytesArray anotherRoleBytes = new BytesArray("{\"b role\": {\"cluster\": [\"manage_security\"]}}"); @@ -1601,7 +1601,7 @@ public void testCacheEntryIsReusedForIdenticalApiKeyRoles() { roleFuture.actionGet(); assertThat(effectiveRoleDescriptors.get(), is(nullValue())); verify(apiKeyService).getApiKeyIdAndRoleBytes(eq(authentication), eq(false)); - verify(apiKeyService).parseRoleDescriptors("key-id-3", anotherRoleBytes); + verify(apiKeyService).parseRoleDescriptors("key-id-3", anotherRoleBytes, ApiKeyService.ApiKeyRoleType.ASSIGNED); } private Authentication createAuthentication() { diff --git a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java b/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java index 790b524085e89..a40f5959b2bd2 100644 --- a/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java +++ b/x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java @@ -17,6 +17,7 @@ import org.elasticsearch.client.RestClient; import org.elasticsearch.cluster.metadata.DataStreamTestHelper; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.xcontent.support.XContentMapValues; @@ -32,6 +33,7 @@ import org.elasticsearch.xcontent.XContentParser; import org.elasticsearch.xcontent.XContentType; import org.elasticsearch.xcontent.json.JsonXContent; +import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.core.slm.SnapshotLifecyclePolicy; import org.elasticsearch.xpack.core.slm.SnapshotLifecycleStats; import org.hamcrest.Matcher; @@ -329,6 +331,90 @@ public void testServiceAccountApiKey() throws IOException { } } + public void testApiKeySuperuser() throws IOException { + if (isRunningAgainstOldCluster()) { + final Request createUserRequest = new Request("PUT", "/_security/user/api_key_super_creator"); + createUserRequest.setJsonEntity(""" + { + "password" : "l0ng-r4nd0m-p@ssw0rd", + "roles" : [ "superuser", "monitoring_user" ] + }"""); + client().performRequest(createUserRequest); + + // Create API key + final Request createApiKeyRequest = new Request("PUT", "/_security/api_key"); + createApiKeyRequest.setOptions( + RequestOptions.DEFAULT.toBuilder() + .addHeader( + "Authorization", + UsernamePasswordToken.basicAuthHeaderValue( + "api_key_super_creator", + new SecureString("l0ng-r4nd0m-p@ssw0rd".toCharArray()) + ) + ) + ); + createApiKeyRequest.setJsonEntity(""" + { + "name": "super_legacy_key" + }"""); + final Map createApiKeyResponse = entityAsMap(client().performRequest(createApiKeyRequest)); + final byte[] keyBytes = (createApiKeyResponse.get("id") + ":" + createApiKeyResponse.get("api_key")).getBytes( + StandardCharsets.UTF_8 + ); + final String apiKeyAuthHeader = "ApiKey " + Base64.getEncoder().encodeToString(keyBytes); + // Save the API key info across restart + final Request saveApiKeyRequest = new Request("PUT", "/api_keys/_doc/super_legacy_key"); + saveApiKeyRequest.setJsonEntity("{\"auth_header\":\"" + apiKeyAuthHeader + "\"}"); + assertOK(client().performRequest(saveApiKeyRequest)); + + if (getOldClusterVersion().before(Version.V_8_0_0)) { + final Request indexRequest = new Request("POST", ".security/_doc"); + indexRequest.setJsonEntity(""" + { + "doc_type": "foo" + }"""); + indexRequest.setOptions( + expectWarnings( + "this request accesses system indices: [.security-7], but in a future major " + + "version, direct access to system indices will be prevented by default" + ).toBuilder().addHeader("Authorization", apiKeyAuthHeader) + ); + assertOK(client().performRequest(indexRequest)); + } + } else { + final Request getRequest = new Request("GET", "/api_keys/_doc/super_legacy_key"); + final Map getResponseMap = responseAsMap(client().performRequest(getRequest)); + @SuppressWarnings("unchecked") + final String apiKeyAuthHeader = ((Map) getResponseMap.get("_source")).get("auth_header"); + + // read is ok + final Request searchRequest = new Request("GET", ".security/_search"); + searchRequest.setOptions( + expectWarnings( + "this request accesses system indices: [.security-7], but in a future major " + + "version, direct access to system indices will be prevented by default" + ).toBuilder().addHeader("Authorization", apiKeyAuthHeader) + ); + assertOK(client().performRequest(searchRequest)); + + // write must not be allowed + final Request indexRequest = new Request("POST", ".security/_doc"); + indexRequest.setJsonEntity(""" + { + "doc_type": "foo" + }"""); + indexRequest.setOptions( + expectWarnings( + "this request accesses system indices: [.security-7], but in a future major " + + "version, direct access to system indices will be prevented by default" + ).toBuilder().addHeader("Authorization", apiKeyAuthHeader) + ); + final ResponseException e = expectThrows(ResponseException.class, () -> client().performRequest(indexRequest)); + assertThat(e.getResponse().getStatusLine().getStatusCode(), equalTo(403)); + assertThat(e.getMessage(), containsString("is unauthorized")); + } + } + /** * Tests that a RollUp job created on a old cluster is correctly restarted after the upgrade. */ From c022c3696f453ce06128dc0e296dbbf9e0b5d78c Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Mon, 17 Jan 2022 15:48:51 +1100 Subject: [PATCH 2/4] expand test --- .../xpack/security/authc/ApiKeyServiceTests.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java index 4d9864135e18e..859b22414342f 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java @@ -562,20 +562,22 @@ public void testValidateApiKey() throws Exception { } public void testGetRolesForApiKeyNotInContext() throws Exception { + final boolean useLegacySuperuserRole = randomBoolean(); + final RoleDescriptor superuserRoleDescriptor = useLegacySuperuserRole ? LEGACY_SUPERUSER_ROLE_DESCRIPTOR : SUPERUSER_ROLE_DESCRIPTOR; Map superUserRdMap; try (XContentBuilder builder = JsonXContent.contentBuilder()) { superUserRdMap = XContentHelper.convertToMap( XContentType.JSON.xContent(), - BytesReference.bytes(SUPERUSER_ROLE_DESCRIPTOR.toXContent(builder, ToXContent.EMPTY_PARAMS, true)).streamInput(), + BytesReference.bytes(superuserRoleDescriptor.toXContent(builder, ToXContent.EMPTY_PARAMS, true)).streamInput(), false ); } Map authMetadata = new HashMap<>(); authMetadata.put(ApiKeyService.API_KEY_ID_KEY, randomAlphaOfLength(12)); - authMetadata.put(API_KEY_ROLE_DESCRIPTORS_KEY, Collections.singletonMap(SUPERUSER_ROLE_DESCRIPTOR.getName(), superUserRdMap)); + authMetadata.put(API_KEY_ROLE_DESCRIPTORS_KEY, Collections.singletonMap(superuserRoleDescriptor.getName(), superUserRdMap)); authMetadata.put( API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY, - Collections.singletonMap(SUPERUSER_ROLE_DESCRIPTOR.getName(), superUserRdMap) + Collections.singletonMap(superuserRoleDescriptor.getName(), superUserRdMap) ); final Authentication authentication = new Authentication( @@ -592,7 +594,12 @@ public void testGetRolesForApiKeyNotInContext() throws Exception { service.getRoleForApiKey(authentication, roleFuture); ApiKeyRoleDescriptors result = roleFuture.get(); assertThat(result.getRoleDescriptors().size(), is(1)); - assertThat(result.getRoleDescriptors().get(0).getName(), is("superuser")); + // Assigned role descriptor should not change + assertThat(result.getRoleDescriptors().get(0), equalTo(superuserRoleDescriptor)); + + assertThat(result.getLimitedByRoleDescriptors().size(), is(1)); + // Limited role descriptor should always be the update superuser descriptor + assertThat(result.getLimitedByRoleDescriptors().get(0), equalTo(SUPERUSER_ROLE_DESCRIPTOR)); } @SuppressWarnings("unchecked") From a7cf578805081e2b3eb102e99b0ed7ed37a6a47f Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Mon, 17 Jan 2022 15:55:51 +1100 Subject: [PATCH 3/4] tweak --- .../elasticsearch/xpack/security/authc/ApiKeyServiceTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java index 859b22414342f..f48088662b4db 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java @@ -598,7 +598,7 @@ public void testGetRolesForApiKeyNotInContext() throws Exception { assertThat(result.getRoleDescriptors().get(0), equalTo(superuserRoleDescriptor)); assertThat(result.getLimitedByRoleDescriptors().size(), is(1)); - // Limited role descriptor should always be the update superuser descriptor + // Limited role descriptor should always be the updated superuser role descriptor assertThat(result.getLimitedByRoleDescriptors().get(0), equalTo(SUPERUSER_ROLE_DESCRIPTOR)); } From f10e930416ba90626d47cd0d36210c56f8d1d3eb Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Mon, 17 Jan 2022 16:19:32 +1100 Subject: [PATCH 4/4] checkstyle --- .../xpack/security/authc/ApiKeyServiceTests.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java index f48088662b4db..1e4f693aeaa55 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java @@ -563,7 +563,9 @@ public void testValidateApiKey() throws Exception { public void testGetRolesForApiKeyNotInContext() throws Exception { final boolean useLegacySuperuserRole = randomBoolean(); - final RoleDescriptor superuserRoleDescriptor = useLegacySuperuserRole ? LEGACY_SUPERUSER_ROLE_DESCRIPTOR : SUPERUSER_ROLE_DESCRIPTOR; + final RoleDescriptor superuserRoleDescriptor = useLegacySuperuserRole + ? LEGACY_SUPERUSER_ROLE_DESCRIPTOR + : SUPERUSER_ROLE_DESCRIPTOR; Map superUserRdMap; try (XContentBuilder builder = JsonXContent.contentBuilder()) { superUserRdMap = XContentHelper.convertToMap( @@ -575,10 +577,7 @@ public void testGetRolesForApiKeyNotInContext() throws Exception { Map authMetadata = new HashMap<>(); authMetadata.put(ApiKeyService.API_KEY_ID_KEY, randomAlphaOfLength(12)); authMetadata.put(API_KEY_ROLE_DESCRIPTORS_KEY, Collections.singletonMap(superuserRoleDescriptor.getName(), superUserRdMap)); - authMetadata.put( - API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY, - Collections.singletonMap(superuserRoleDescriptor.getName(), superUserRdMap) - ); + authMetadata.put(API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY, Collections.singletonMap(superuserRoleDescriptor.getName(), superUserRdMap)); final Authentication authentication = new Authentication( new User("joe"),