diff --git a/x-pack/plugin/ilm/qa/with-security/src/javaRestTest/java/org/elasticsearch/xpack/security/PermissionsIT.java b/x-pack/plugin/ilm/qa/with-security/src/javaRestTest/java/org/elasticsearch/xpack/security/PermissionsIT.java index 4d2df7d925397..4c30f598cd94d 100644 --- a/x-pack/plugin/ilm/qa/with-security/src/javaRestTest/java/org/elasticsearch/xpack/security/PermissionsIT.java +++ b/x-pack/plugin/ilm/qa/with-security/src/javaRestTest/java/org/elasticsearch/xpack/security/PermissionsIT.java @@ -146,7 +146,7 @@ public void testCanManageIndexWithNoPermissions() throws Exception { assertThat(stepInfo.get("reason"), equalTo("action [indices:monitor/stats] is unauthorized" + " for user [test_ilm]" + " on indices [not-ilm]," + - " this action is granted by the privileges [monitor,manage,all]")); + " this action is granted by the index privileges [monitor,manage,all]")); } }); } diff --git a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/authc/ApiKeyIntegTests.java b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/authc/ApiKeyIntegTests.java index 8c54c78c376b5..cadf5020bf423 100644 --- a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/authc/ApiKeyIntegTests.java +++ b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/authc/ApiKeyIntegTests.java @@ -1217,14 +1217,14 @@ private Client getClientForRunAsUser() { private void assertErrorMessage(final ElasticsearchSecurityException ese, String action, String userName, String apiKeyId) { assertThat(ese, throwableWithMessage( containsString("action [" + action + "] is unauthorized for API key id [" + apiKeyId + "] of user [" + userName + "]"))); - assertThat(ese, throwableWithMessage(containsString(", this action is granted by the privileges ["))); + assertThat(ese, throwableWithMessage(containsString(", this action is granted by the cluster privileges ["))); assertThat(ese, throwableWithMessage(containsString("manage_api_key,manage_security,all]"))); } private void assertErrorMessage(final ElasticsearchSecurityException ese, String action, String userName) { assertThat(ese, throwableWithMessage( containsString("action [" + action + "] is unauthorized for user [" + userName + "]"))); - assertThat(ese, throwableWithMessage(containsString(", this action is granted by the privileges ["))); + assertThat(ese, throwableWithMessage(containsString(", this action is granted by the cluster privileges ["))); assertThat(ese, throwableWithMessage(containsString("manage_api_key,manage_security,all]"))); } } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java index 60af63f313c49..fdb822b0a76ae 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java @@ -635,15 +635,17 @@ private ElasticsearchSecurityException denialException(Authentication authentica message = message + " " + context; } - if (isIndexAction(action)) { - final Collection privileges = IndexPrivilege.findPrivilegesThatGrant(action); + if (ClusterPrivilegeResolver.isClusterAction(action)) { + final Collection privileges = ClusterPrivilegeResolver.findPrivilegesThatGrant(action, request, authentication); if (privileges != null && privileges.size() > 0) { - message = message + ", this action is granted by the privileges [" + collectionToCommaDelimitedString(privileges) + "]"; + message = message + ", this action is granted by the cluster privileges [" + + collectionToCommaDelimitedString(privileges) + "]"; } - } else if (ClusterPrivilegeResolver.isClusterAction(action)) { - final Collection privileges = ClusterPrivilegeResolver.findPrivilegesThatGrant(action, request, authentication); + } else if (isIndexAction(action)) { + final Collection privileges = IndexPrivilege.findPrivilegesThatGrant(action); if (privileges != null && privileges.size() > 0) { - message = message + ", this action is granted by the privileges [" + collectionToCommaDelimitedString(privileges) + "]"; + message = message + ", this action is granted by the index privileges [" + + collectionToCommaDelimitedString(privileges) + "]"; } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index 03784207a7ff6..15424cf068c06 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -36,6 +36,8 @@ import org.elasticsearch.action.admin.indices.shards.IndicesShardStoresRequest; import org.elasticsearch.action.admin.indices.stats.IndicesStatsAction; import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequest; +import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateAction; +import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest; import org.elasticsearch.action.bulk.BulkAction; import org.elasticsearch.action.bulk.BulkItemRequest; import org.elasticsearch.action.bulk.BulkRequest; @@ -285,9 +287,9 @@ auditTrailService, new DefaultAuthenticationFailureHandler(Collections.emptyMap( private void authorize(Authentication authentication, String action, TransportRequest request) { PlainActionFuture done = new PlainActionFuture<>(); - PlainActionFuture indicesPermissions = new PlainActionFuture<>(); - PlainActionFuture originatingAction = new PlainActionFuture<>(); - PlainActionFuture authorizationInfo = new PlainActionFuture<>(); + PlainActionFuture indicesPermissions = new PlainActionFuture<>(); + PlainActionFuture originatingAction = new PlainActionFuture<>(); + PlainActionFuture authorizationInfo = new PlainActionFuture<>(); String someRandomHeader = "test_" + UUIDs.randomBase64UUID(); Object someRandomHeaderValue = mock(Object.class); threadContext.putTransient(someRandomHeader, someRandomHeaderValue); @@ -371,23 +373,23 @@ public void testActionsForSystemUserIsAuthorized() throws IOException { // A failure would throw an exception final Authentication authentication = createAuthentication(SystemUser.INSTANCE); final String[] actions = { - "indices:monitor/whatever", - "internal:whatever", - "cluster:monitor/whatever", - "cluster:admin/reroute", - "indices:admin/mapping/put", - "indices:admin/template/put", - "indices:admin/seq_no/global_checkpoint_sync", - "indices:admin/seq_no/retention_lease_sync", - "indices:admin/seq_no/retention_lease_background_sync", - "indices:admin/seq_no/add_retention_lease", - "indices:admin/seq_no/remove_retention_lease", - "indices:admin/seq_no/renew_retention_lease", - "indices:admin/settings/update" }; + "indices:monitor/whatever", + "internal:whatever", + "cluster:monitor/whatever", + "cluster:admin/reroute", + "indices:admin/mapping/put", + "indices:admin/template/put", + "indices:admin/seq_no/global_checkpoint_sync", + "indices:admin/seq_no/retention_lease_sync", + "indices:admin/seq_no/retention_lease_background_sync", + "indices:admin/seq_no/add_retention_lease", + "indices:admin/seq_no/remove_retention_lease", + "indices:admin/seq_no/renew_retention_lease", + "indices:admin/settings/update"}; for (String action : actions) { authorize(authentication, action, request); verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(action), eq(request), - authzInfoRoles(new String[] { SystemUser.ROLE_NAME })); + authzInfoRoles(new String[]{SystemUser.ROLE_NAME})); } verifyNoMoreInteractions(auditTrail); @@ -397,13 +399,13 @@ public void testAuthorizationForSecurityChange() { final Authentication authentication = createAuthentication(new User("user", "manage_security_role")); final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); RoleDescriptor role = new RoleDescriptor("manage_security_role", new String[]{ClusterPrivilegeResolver.MANAGE_SECURITY.name()}, - null,null, null, null, null, null); + null, null, null, null, null, null); roleMap.put("manage_security_role", role); for (String action : LoggingAuditTrail.SECURITY_CHANGE_ACTIONS) { TransportRequest request = mock(TransportRequest.class); authorize(authentication, action, request); verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(action), eq(request), - authzInfoRoles(new String[]{role.getName()})); + authzInfoRoles(new String[]{role.getName()})); } verifyNoMoreInteractions(auditTrail); } @@ -428,7 +430,7 @@ public void testClusterAdminActionsForSystemUserWhichAreNotAuthorized() throws I () -> authorize(authentication, "cluster:admin/whatever", request), "cluster:admin/whatever", SystemUser.INSTANCE.principal()); verify(auditTrail).accessDenied(eq(requestId), eq(authentication), eq("cluster:admin/whatever"), eq(request), - authzInfoRoles(new String[] { SystemUser.ROLE_NAME })); + authzInfoRoles(new String[]{SystemUser.ROLE_NAME})); verifyNoMoreInteractions(auditTrail); } @@ -440,7 +442,7 @@ public void testClusterAdminSnapshotStatusActionForSystemUserWhichIsNotAuthorize () -> authorize(authentication, "cluster:admin/snapshot/status", request), "cluster:admin/snapshot/status", SystemUser.INSTANCE.principal()); verify(auditTrail).accessDenied(eq(requestId), eq(authentication), eq("cluster:admin/snapshot/status"), eq(request), - authzInfoRoles(new String[] { SystemUser.ROLE_NAME })); + authzInfoRoles(new String[]{SystemUser.ROLE_NAME})); verifyNoMoreInteractions(auditTrail); } @@ -457,11 +459,11 @@ public ClusterPermission.Builder buildPermission(ClusterPermission.Builder build return builder; } }; - final ConfigurableClusterPrivilege[] configurableClusterPrivileges = new ConfigurableClusterPrivilege[] { + final ConfigurableClusterPrivilege[] configurableClusterPrivileges = new ConfigurableClusterPrivilege[]{ configurableClusterPrivilege }; final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); - RoleDescriptor role = new RoleDescriptor("role1", null, null, null, configurableClusterPrivileges, null, null ,null); + RoleDescriptor role = new RoleDescriptor("role1", null, null, null, configurableClusterPrivileges, null, null, null); roleMap.put("role1", role); authorize(authentication, DeletePrivilegesAction.NAME, request); @@ -483,11 +485,11 @@ public ClusterPermission.Builder buildPermission(ClusterPermission.Builder build return builder; } }; - final ConfigurableClusterPrivilege[] configurableClusterPrivileges = new ConfigurableClusterPrivilege[] { + final ConfigurableClusterPrivilege[] configurableClusterPrivileges = new ConfigurableClusterPrivilege[]{ configurableClusterPrivilege }; final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); - RoleDescriptor role = new RoleDescriptor("role1", null, null, null, configurableClusterPrivileges, null, null ,null); + RoleDescriptor role = new RoleDescriptor("role1", null, null, null, configurableClusterPrivileges, null, null, null); roleMap.put("role1", role); assertThrowsAuthorizationException( @@ -530,7 +532,7 @@ public void testUserWithNoRolesPerformsRemoteSearchWithScroll() { final Authentication authentication = createAuthentication(new User("test user")); mockEmptyMetadata(); final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); - for (final boolean hasLocalIndices: List.of(true, false)) { + for (final boolean hasLocalIndices : List.of(true, false)) { when(parsedScrollId.hasLocalIndices()).thenReturn(hasLocalIndices); if (hasLocalIndices) { assertThrowsAuthorizationException( @@ -538,12 +540,12 @@ public void testUserWithNoRolesPerformsRemoteSearchWithScroll() { "indices:data/read/scroll", "test user" ); verify(auditTrail).accessDenied(eq(requestId), eq(authentication), - eq("indices:data/read/scroll"), eq(searchScrollRequest), - authzInfoRoles(Role.EMPTY.names())); + eq("indices:data/read/scroll"), eq(searchScrollRequest), + authzInfoRoles(Role.EMPTY.names())); } else { authorize(authentication, SearchScrollAction.NAME, searchScrollRequest); verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(SearchScrollAction.NAME), eq(searchScrollRequest), - authzInfoRoles(Role.EMPTY.names())); + authzInfoRoles(Role.EMPTY.names())); } verifyNoMoreInteractions(auditTrail); } @@ -621,8 +623,8 @@ public void testUserWithNoRolesOpenPointInTimeWithRemoteIndices() { final Authentication authentication = createAuthentication(new User("test user")); mockEmptyMetadata(); final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); - for (final boolean hasLocalIndices: List.of(true, false)) { - final String[] indices = new String[] { + for (final boolean hasLocalIndices : List.of(true, false)) { + final String[] indices = new String[]{ hasLocalIndices ? randomAlphaOfLength(5) : "other_cluster:" + randomFrom(randomAlphaOfLength(5), "*", randomAlphaOfLength(4) + "*"), @@ -638,13 +640,13 @@ public void testUserWithNoRolesOpenPointInTimeWithRemoteIndices() { "indices:data/read/open_point_in_time", "test user" ); verify(auditTrail).accessDenied(eq(requestId), eq(authentication), - eq("indices:data/read/open_point_in_time"), eq(openPointInTimeRequest), - authzInfoRoles(Role.EMPTY.names())); + eq("indices:data/read/open_point_in_time"), eq(openPointInTimeRequest), + authzInfoRoles(Role.EMPTY.names())); } else { authorize(authentication, OpenPointInTimeAction.NAME, openPointInTimeRequest); verify(auditTrail).accessGranted(eq(requestId), eq(authentication), - eq("indices:data/read/open_point_in_time"), eq(openPointInTimeRequest), - authzInfoRoles(Role.EMPTY.names())); + eq("indices:data/read/open_point_in_time"), eq(openPointInTimeRequest), + authzInfoRoles(Role.EMPTY.names())); } verifyNoMoreInteractions(auditTrail); } @@ -657,8 +659,8 @@ public void testUserWithNoRolesCanClosePointInTime() { final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); authorize(authentication, ClosePointInTimeAction.NAME, closePointInTimeRequest); verify(auditTrail).accessGranted(eq(requestId), eq(authentication), - eq("indices:data/read/close_point_in_time"), eq(closePointInTimeRequest), - authzInfoRoles(Role.EMPTY.names())); + eq("indices:data/read/close_point_in_time"), eq(closePointInTimeRequest), + authzInfoRoles(Role.EMPTY.names())); verifyNoMoreInteractions(auditTrail); } @@ -676,7 +678,7 @@ public void testUnknownRoleCausesDenial() throws IOException { () -> authorize(authentication, action, request)); assertThat(securityException, throwableWithMessage(containsString("[" + action + "] is unauthorized for user [test user] on indices ["))); - assertThat(securityException, throwableWithMessage(containsString("this action is granted by the privileges [read,all]"))); + assertThat(securityException, throwableWithMessage(containsString("this action is granted by the index privileges [read,all]"))); verify(auditTrail).accessDenied(eq(requestId), eq(authentication), eq(action), eq(request), authzInfoRoles(Role.EMPTY.names())); verifyNoMoreInteractions(auditTrail); @@ -715,7 +717,7 @@ public void testThatRoleWithNoIndicesIsDenied() throws IOException { () -> authorize(authentication, action, request)); assertThat(securityException, throwableWithMessage(containsString("[" + action + "] is unauthorized for user [test user] on indices ["))); - assertThat(securityException, throwableWithMessage(containsString("this action is granted by the privileges [read,all]"))); + assertThat(securityException, throwableWithMessage(containsString("this action is granted by the index privileges [read,all]"))); verify(auditTrail).accessDenied(eq(requestId), eq(authentication), eq(action), eq(request), authzInfoRoles(new String[]{role.getName()})); @@ -906,7 +908,7 @@ public void testDenialErrorMessagesForSearchAction() throws IOException { assertThat(securityException, throwableWithMessage(containsString("other-4"))); assertThat(securityException, throwableWithMessage(not(containsString("all-1")))); assertThat(securityException, throwableWithMessage(not(containsString("read-2")))); - assertThat(securityException, throwableWithMessage(containsString(", this action is granted by the privileges [read,all]"))); + assertThat(securityException, throwableWithMessage(containsString(", this action is granted by the index privileges [read,all]"))); } public void testDenialErrorMessagesForBulkIngest() throws Exception { @@ -948,15 +950,15 @@ public void testDenialErrorMessagesForBulkIngest() throws Exception { assertThat(response.getResponses(), arrayWithSize(3)); assertThat(response.getResponses()[0].getFailureMessage(), containsString("unauthorized for user [" + user.principal() + "]")); assertThat(response.getResponses()[0].getFailureMessage(), containsString("on indices [" + index + "]")); - assertThat(response.getResponses()[0].getFailureMessage(), containsString("[create_doc,create,index,write,all]") ); - assertThat(response.getResponses()[1].getFailureMessage(), containsString("[create,index,write,all]") ); - assertThat(response.getResponses()[2].getFailureMessage(), containsString("[delete,write,all]") ); + assertThat(response.getResponses()[0].getFailureMessage(), containsString("[create_doc,create,index,write,all]")); + assertThat(response.getResponses()[1].getFailureMessage(), containsString("[create,index,write,all]")); + assertThat(response.getResponses()[2].getFailureMessage(), containsString("[delete,write,all]")); } public void testDenialErrorMessagesForClusterHealthAction() throws IOException { RoleDescriptor role = new RoleDescriptor("role_" + randomAlphaOfLengthBetween(3, 6), new String[0], // no cluster privileges - new IndicesPrivileges[] { IndicesPrivileges.builder().indices("index-*").privileges("all").build() } , null); + new IndicesPrivileges[]{IndicesPrivileges.builder().indices("index-*").privileges("all").build()}, null); User user = new User(randomAlphaOfLengthBetween(6, 8), role.getName()); final Authentication authentication = createAuthentication(user); roleMap.put(role.getName(), role); @@ -970,7 +972,33 @@ public void testDenialErrorMessagesForClusterHealthAction() throws IOException { assertThat(securityException, throwableWithMessage( containsString("[" + ClusterHealthAction.NAME + "] is unauthorized for user [" + user.principal() + "]"))); assertThat(securityException, - throwableWithMessage(containsString("this action is granted by the privileges [monitor,manage,all]"))); + throwableWithMessage(containsString("this action is granted by the cluster privileges [monitor,manage,all]"))); + } + + /** + * Per {@link ClusterPrivilegeResolver#isClusterAction(String)}, there are some actions that start with "indices:" but are treated as + * cluster level actions for the purposes of security. + * This test case checks that the error message for these actions handles this edge-case. + */ + public void testDenialErrorMessagesForIndexTemplateAction() throws IOException { + RoleDescriptor role = new RoleDescriptor("role_" + randomAlphaOfLengthBetween(3, 6), + new String[0], // no cluster privileges + new IndicesPrivileges[0], // no index privileges + null); + User user = new User(randomAlphaOfLengthBetween(6, 8), role.getName()); + final Authentication authentication = createAuthentication(user); + roleMap.put(role.getName(), role); + + AuditUtil.getOrGenerateRequestId(threadContext); + + TransportRequest request = new PutIndexTemplateRequest(randomAlphaOfLengthBetween(4, 20)); + + ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class, + () -> authorize(authentication, PutIndexTemplateAction.NAME, request)); + assertThat(securityException, throwableWithMessage( + containsString("[" + PutIndexTemplateAction.NAME + "] is unauthorized for user [" + user.principal() + "]"))); + assertThat(securityException, + throwableWithMessage(containsString("this action is granted by the cluster privileges [manage_index_templates,manage,all]"))); } public void testDenialErrorMessagesForInvalidateApiKeyAction() throws IOException { @@ -992,7 +1020,8 @@ public void testDenialErrorMessagesForInvalidateApiKeyAction() throws IOExceptio assertThat(securityException, throwableWithMessage( containsString("[" + InvalidateApiKeyAction.NAME + "] is unauthorized for user [" + user.principal() + "]"))); assertThat(securityException, throwableWithMessage( - containsString("this action is granted by the privileges [manage_own_api_key,manage_api_key,manage_security,all]"))); + containsString("this action is granted by the cluster privileges [manage_own_api_key,manage_api_key,manage_security,all]") + )); } // All API Keys @@ -1004,7 +1033,7 @@ public void testDenialErrorMessagesForInvalidateApiKeyAction() throws IOExceptio assertThat(securityException, throwableWithMessage( containsString("[" + InvalidateApiKeyAction.NAME + "] is unauthorized for user [" + user.principal() + "]"))); assertThat(securityException, throwableWithMessage( - containsString("this action is granted by the privileges [manage_api_key,manage_security,all]"))); + containsString("this action is granted by the cluster privileges [manage_api_key,manage_security,all]"))); } } @@ -1019,7 +1048,7 @@ public void testDenialForAnonymousUser() throws IOException { new IndexNameExpressionResolver(new ThreadContext(Settings.EMPTY)), operatorPrivilegesService); RoleDescriptor role = new RoleDescriptor("a_all", null, - new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null); + new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null); roleMap.put("a_all", role); final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); @@ -1109,7 +1138,7 @@ public void testRunAsRequestWithoutLookedUpBy() throws IOException { () -> authorize(authentication, AuthenticateAction.NAME, request), AuthenticateAction.NAME, "test user", "run as me"); // run as [run as me] verify(auditTrail).runAsDenied(eq(requestId), eq(authentication), eq(AuthenticateAction.NAME), eq(request), - authzInfoRoles(new String[] { ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName() })); + authzInfoRoles(new String[]{ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName()})); verifyNoMoreInteractions(auditTrail); } @@ -1214,40 +1243,40 @@ public void testGrantAllRestrictedUserCannotExecuteOperationAgainstSecurityIndic when(clusterService.state()).thenReturn(state); when(state.metadata()).thenReturn(Metadata.builder() .put(new IndexMetadata.Builder(INTERNAL_SECURITY_MAIN_INDEX_7) - .putAlias(new AliasMetadata.Builder(SECURITY_MAIN_ALIAS).build()) - .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) - .numberOfShards(1) - .numberOfReplicas(0) - .build(),true) + .putAlias(new AliasMetadata.Builder(SECURITY_MAIN_ALIAS).build()) + .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) + .numberOfShards(1) + .numberOfReplicas(0) + .build(), true) .build()); final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); List> requests = new ArrayList<>(); requests.add(new Tuple<>(BulkAction.NAME + "[s]", - new DeleteRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); + new DeleteRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); requests.add( - new Tuple<>(UpdateAction.NAME, new UpdateRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); + new Tuple<>(UpdateAction.NAME, new UpdateRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); requests.add( - new Tuple<>(BulkAction.NAME + "[s]", new IndexRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); + new Tuple<>(BulkAction.NAME + "[s]", new IndexRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); requests.add(new Tuple<>(TermVectorsAction.NAME, - new TermVectorsRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); + new TermVectorsRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); requests.add(new Tuple<>(GetAction.NAME, new GetRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); requests.add(new Tuple<>(IndicesAliasesAction.NAME, new IndicesAliasesRequest() - .addAliasAction(AliasActions.add().alias("security_alias").index(INTERNAL_SECURITY_MAIN_INDEX_7)))); + .addAliasAction(AliasActions.add().alias("security_alias").index(INTERNAL_SECURITY_MAIN_INDEX_7)))); requests.add(new Tuple<>(UpdateSettingsAction.NAME, - new UpdateSettingsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); + new UpdateSettingsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); // cannot execute monitor operations requests.add(new Tuple<>(IndicesStatsAction.NAME, - new IndicesStatsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); + new IndicesStatsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); requests.add(new Tuple<>(RecoveryAction.NAME, - new RecoveryRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); + new RecoveryRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); requests.add(new Tuple<>(IndicesSegmentsAction.NAME, - new IndicesSegmentsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); + new IndicesSegmentsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); requests.add(new Tuple<>(GetSettingsAction.NAME, - new GetSettingsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); + new GetSettingsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); requests.add(new Tuple<>(IndicesShardStoresAction.NAME, - new IndicesShardStoresRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); + new IndicesShardStoresRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); for (Tuple requestTuple : requests) { String action = requestTuple.v1(); @@ -1281,20 +1310,20 @@ public void testGrantAllRestrictedUserCannotExecuteOperationAgainstSecurityIndic public void testMonitoringOperationsAgainstSecurityIndexRequireAllowRestricted() throws IOException { final RoleDescriptor restrictedMonitorRole = new RoleDescriptor("restricted_monitor", null, - new IndicesPrivileges[] { IndicesPrivileges.builder().indices("*").privileges("monitor").build() }, null); - final RoleDescriptor unrestrictedMonitorRole = new RoleDescriptor("unrestricted_monitor", null, new IndicesPrivileges[] { - IndicesPrivileges.builder().indices("*").privileges("monitor").allowRestrictedIndices(true).build() }, null); + new IndicesPrivileges[]{IndicesPrivileges.builder().indices("*").privileges("monitor").build()}, null); + final RoleDescriptor unrestrictedMonitorRole = new RoleDescriptor("unrestricted_monitor", null, new IndicesPrivileges[]{ + IndicesPrivileges.builder().indices("*").privileges("monitor").allowRestrictedIndices(true).build()}, null); roleMap.put("restricted_monitor", restrictedMonitorRole); roleMap.put("unrestricted_monitor", unrestrictedMonitorRole); ClusterState state = mock(ClusterState.class); when(clusterService.state()).thenReturn(state); when(state.metadata()).thenReturn(Metadata.builder() .put(new IndexMetadata.Builder(INTERNAL_SECURITY_MAIN_INDEX_7) - .putAlias(new AliasMetadata.Builder(SECURITY_MAIN_ALIAS).build()) - .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) - .numberOfShards(1) - .numberOfReplicas(0) - .build(), true) + .putAlias(new AliasMetadata.Builder(SECURITY_MAIN_ALIAS).build()) + .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) + .numberOfShards(1) + .numberOfReplicas(0) + .build(), true) .build()); List> requests = new ArrayList<>(); @@ -1312,7 +1341,7 @@ public void testMonitoringOperationsAgainstSecurityIndexRequireAllowRestricted() final Authentication restrictedUserAuthn = createAuthentication(new User("restricted_user", "restricted_monitor")); assertThrowsAuthorizationException(() -> authorize(restrictedUserAuthn, action, request), action, "restricted_user"); verify(auditTrail).accessDenied(eq(requestId), eq(restrictedUserAuthn), eq(action), eq(request), - authzInfoRoles(new String[] { "restricted_monitor" })); + authzInfoRoles(new String[]{"restricted_monitor"})); verifyNoMoreInteractions(auditTrail); } try (StoredContext ignore = threadContext.stashContext()) { @@ -1320,7 +1349,7 @@ public void testMonitoringOperationsAgainstSecurityIndexRequireAllowRestricted() final Authentication unrestrictedUserAuthn = createAuthentication(new User("unrestricted_user", "unrestricted_monitor")); authorize(unrestrictedUserAuthn, action, request); verify(auditTrail).accessGranted(eq(requestId), eq(unrestrictedUserAuthn), eq(action), eq(request), - authzInfoRoles(new String[] { "unrestricted_monitor" })); + authzInfoRoles(new String[]{"unrestricted_monitor"})); verifyNoMoreInteractions(auditTrail); } } @@ -1333,38 +1362,38 @@ public void testSuperusersCanExecuteOperationAgainstSecurityIndex() throws IOExc when(clusterService.state()).thenReturn(state); when(state.metadata()).thenReturn(Metadata.builder() .put(new IndexMetadata.Builder(INTERNAL_SECURITY_MAIN_INDEX_7) - .putAlias(new AliasMetadata.Builder(SECURITY_MAIN_ALIAS).build()) - .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) - .numberOfShards(1) - .numberOfReplicas(0) - .build(), true) + .putAlias(new AliasMetadata.Builder(SECURITY_MAIN_ALIAS).build()) + .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) + .numberOfShards(1) + .numberOfReplicas(0) + .build(), true) .build()); final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); List> requests = new ArrayList<>(); requests.add( - new Tuple<>(DeleteAction.NAME, new DeleteRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); + new Tuple<>(DeleteAction.NAME, new DeleteRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); requests.add(new Tuple<>(BulkAction.NAME + "[s]", - createBulkShardRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), DeleteRequest::new))); + createBulkShardRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), DeleteRequest::new))); requests.add( - new Tuple<>(UpdateAction.NAME, new UpdateRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); + new Tuple<>(UpdateAction.NAME, new UpdateRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); requests.add(new Tuple<>(IndexAction.NAME, new IndexRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); requests.add(new Tuple<>(BulkAction.NAME + "[s]", - createBulkShardRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), - (index, id) -> new IndexRequest(index).id(id)))); + createBulkShardRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), + (index, id) -> new IndexRequest(index).id(id)))); requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); requests.add(new Tuple<>(TermVectorsAction.NAME, - new TermVectorsRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); + new TermVectorsRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); requests.add( - new Tuple<>(GetAction.NAME, new GetRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); + new Tuple<>(GetAction.NAME, new GetRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); requests.add(new Tuple<>(TermVectorsAction.NAME, - new TermVectorsRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); + new TermVectorsRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id"))); requests.add(new Tuple<>(IndicesAliasesAction.NAME, new IndicesAliasesRequest() - .addAliasAction(AliasActions.add().alias("security_alias").index(INTERNAL_SECURITY_MAIN_INDEX_7)))); + .addAliasAction(AliasActions.add().alias("security_alias").index(INTERNAL_SECURITY_MAIN_INDEX_7)))); requests.add(new Tuple<>(ClusterHealthAction.NAME, - new ClusterHealthRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); + new ClusterHealthRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7)))); requests.add(new Tuple<>(ClusterHealthAction.NAME, - new ClusterHealthRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "foo", "bar"))); + new ClusterHealthRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "foo", "bar"))); for (final Tuple requestTuple : requests) { final String action = requestTuple.v1(); @@ -1386,11 +1415,11 @@ public void testSuperusersCanExecuteOperationAgainstSecurityIndexWithWildcard() when(clusterService.state()).thenReturn(state); when(state.metadata()).thenReturn(Metadata.builder() .put(new IndexMetadata.Builder(INTERNAL_SECURITY_MAIN_INDEX_7) - .putAlias(new AliasMetadata.Builder(SECURITY_MAIN_ALIAS).build()) - .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) - .numberOfShards(1) - .numberOfReplicas(0) - .build(), true) + .putAlias(new AliasMetadata.Builder(SECURITY_MAIN_ALIAS).build()) + .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) + .numberOfShards(1) + .numberOfReplicas(0) + .build(), true) .build()); final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); @@ -1414,7 +1443,7 @@ public void testCompositeActionsAreImmediatelyRejected() { assertThrowsAuthorizationException( () -> authorize(authentication, action, request), action, "test user"); verify(auditTrail).accessDenied(eq(requestId), eq(authentication), eq(action), eq(request), - authzInfoRoles(new String[] { role.getName() })); + authzInfoRoles(new String[]{role.getName()})); verifyNoMoreInteractions(auditTrail); } @@ -1432,7 +1461,7 @@ public void testCompositeActionsIndicesAreNotChecked() throws IOException { authorize(authentication, action, request); verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(action), eq(request), - authzInfoRoles(new String[] { role.getName() })); + authzInfoRoles(new String[]{role.getName()})); verifyNoMoreInteractions(auditTrail); } @@ -1521,25 +1550,25 @@ public void testAuthorizationOfIndividualBulkItems() throws IOException { authorize(authentication, action, request); verify(auditTrail).explicitIndexAccessEvent(eq(requestId), eq(AuditLevel.ACCESS_GRANTED), eq(authentication), - eq(DeleteAction.NAME), eq("concrete-index"), eq(BulkItemRequest.class.getSimpleName()), - eq(request.remoteAddress()), authzInfoRoles(new String[] { role.getName() })); + eq(DeleteAction.NAME), eq("concrete-index"), eq(BulkItemRequest.class.getSimpleName()), + eq(request.remoteAddress()), authzInfoRoles(new String[]{role.getName()})); verify(auditTrail).explicitIndexAccessEvent(eq(requestId), eq(AuditLevel.ACCESS_GRANTED), eq(authentication), - eq(DeleteAction.NAME), eq("alias-2"), eq(BulkItemRequest.class.getSimpleName()), - eq(request.remoteAddress()), authzInfoRoles(new String[] { role.getName() })); + eq(DeleteAction.NAME), eq("alias-2"), eq(BulkItemRequest.class.getSimpleName()), + eq(request.remoteAddress()), authzInfoRoles(new String[]{role.getName()})); verify(auditTrail).explicitIndexAccessEvent(eq(requestId), eq(AuditLevel.ACCESS_GRANTED), eq(authentication), - eq(IndexAction.NAME + ":op_type/index"), eq("concrete-index"), eq(BulkItemRequest.class.getSimpleName()), - eq(request.remoteAddress()), authzInfoRoles(new String[] { role.getName() })); + eq(IndexAction.NAME + ":op_type/index"), eq("concrete-index"), eq(BulkItemRequest.class.getSimpleName()), + eq(request.remoteAddress()), authzInfoRoles(new String[]{role.getName()})); verify(auditTrail).explicitIndexAccessEvent(eq(requestId), eq(AuditLevel.ACCESS_GRANTED), eq(authentication), - eq(IndexAction.NAME + ":op_type/index"), eq("alias-1"), eq(BulkItemRequest.class.getSimpleName()), - eq(request.remoteAddress()), authzInfoRoles(new String[] { role.getName() })); + eq(IndexAction.NAME + ":op_type/index"), eq("alias-1"), eq(BulkItemRequest.class.getSimpleName()), + eq(request.remoteAddress()), authzInfoRoles(new String[]{role.getName()})); verify(auditTrail).explicitIndexAccessEvent(eq(requestId), eq(AuditLevel.ACCESS_DENIED), eq(authentication), - eq(DeleteAction.NAME), eq("alias-1"), eq(BulkItemRequest.class.getSimpleName()), - eq(request.remoteAddress()), authzInfoRoles(new String[] { role.getName() })); + eq(DeleteAction.NAME), eq("alias-1"), eq(BulkItemRequest.class.getSimpleName()), + eq(request.remoteAddress()), authzInfoRoles(new String[]{role.getName()})); verify(auditTrail).explicitIndexAccessEvent(eq(requestId), eq(AuditLevel.ACCESS_DENIED), eq(authentication), - eq(IndexAction.NAME + ":op_type/index"), eq("alias-2"), eq(BulkItemRequest.class.getSimpleName()), - eq(request.remoteAddress()), authzInfoRoles(new String[] { role.getName() })); + eq(IndexAction.NAME + ":op_type/index"), eq("alias-2"), eq(BulkItemRequest.class.getSimpleName()), + eq(request.remoteAddress()), authzInfoRoles(new String[]{role.getName()})); verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(action), eq(request), - authzInfoRoles(new String[] { role.getName() })); // bulk request is allowed + authzInfoRoles(new String[]{role.getName()})); // bulk request is allowed verifyNoMoreInteractions(auditTrail); } @@ -1567,11 +1596,11 @@ public void testAuthorizationOfIndividualBulkItemsWithDateMath() throws IOExcept // both deletes should fail verify(auditTrail, times(2)).explicitIndexAccessEvent(eq(requestId), eq(AuditLevel.ACCESS_DENIED), eq(authentication), - eq(DeleteAction.NAME), Matchers.startsWith("datemath-"), eq(BulkItemRequest.class.getSimpleName()), - eq(request.remoteAddress()), authzInfoRoles(new String[] { role.getName() })); + eq(DeleteAction.NAME), Matchers.startsWith("datemath-"), eq(BulkItemRequest.class.getSimpleName()), + eq(request.remoteAddress()), authzInfoRoles(new String[]{role.getName()})); verify(auditTrail, times(2)).explicitIndexAccessEvent(eq(requestId), eq(AuditLevel.ACCESS_GRANTED), eq(authentication), - eq(IndexAction.NAME + ":op_type/index"), Matchers.startsWith("datemath-"), eq(BulkItemRequest.class.getSimpleName()), - eq(request.remoteAddress()), authzInfoRoles(new String[] { role.getName() })); + eq(IndexAction.NAME + ":op_type/index"), Matchers.startsWith("datemath-"), eq(BulkItemRequest.class.getSimpleName()), + eq(request.remoteAddress()), authzInfoRoles(new String[]{role.getName()})); // bulk request is allowed verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(action), eq(request), authzInfoRoles(new String[]{role.getName()})); diff --git a/x-pack/plugin/src/test/resources/rest-api-spec/test/api_key/11_invalidation.yml b/x-pack/plugin/src/test/resources/rest-api-spec/test/api_key/11_invalidation.yml index 06f75cbb8ac16..6d11f3eabfcb3 100644 --- a/x-pack/plugin/src/test/resources/rest-api-spec/test/api_key/11_invalidation.yml +++ b/x-pack/plugin/src/test/resources/rest-api-spec/test/api_key/11_invalidation.yml @@ -126,7 +126,7 @@ teardown: "username": "api_key_manager" } - match: { "error.type": "security_exception" } - - match: { "error.reason": "action [cluster:admin/xpack/security/api_key/invalidate] is unauthorized for user [api_key_user_1], this action is granted by the privileges [manage_api_key,manage_security,all]" } + - match: { "error.reason": "action [cluster:admin/xpack/security/api_key/invalidate] is unauthorized for user [api_key_user_1], this action is granted by the cluster privileges [manage_api_key,manage_security,all]" } - do: headers: @@ -189,7 +189,7 @@ teardown: "realm_name": "default_native" } - match: { "error.type": "security_exception" } - - match: { "error.reason": "action [cluster:admin/xpack/security/api_key/invalidate] is unauthorized for user [api_key_user_1], this action is granted by the privileges [manage_api_key,manage_security,all]" } + - match: { "error.reason": "action [cluster:admin/xpack/security/api_key/invalidate] is unauthorized for user [api_key_user_1], this action is granted by the cluster privileges [manage_api_key,manage_security,all]" } - do: headers: