|  | @@ -25,12 +25,14 @@ import org.elasticsearch.cluster.metadata.IndexAbstraction;
 | 
	
		
			
				|  |  |  import org.elasticsearch.cluster.metadata.IndexMetadata;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.Strings;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.bytes.BytesArray;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.bytes.BytesReference;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.collect.MapBuilder;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.settings.Settings;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.util.set.Sets;
 | 
	
		
			
				|  |  |  import org.elasticsearch.core.Tuple;
 | 
	
		
			
				|  |  |  import org.elasticsearch.license.GetLicenseAction;
 | 
	
		
			
				|  |  |  import org.elasticsearch.test.ESTestCase;
 | 
	
		
			
				|  |  | +import org.elasticsearch.transport.TcpTransport;
 | 
	
		
			
				|  |  |  import org.elasticsearch.transport.TransportRequest;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xcontent.XContentType;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.XPackPlugin;
 | 
	
	
		
			
				|  | @@ -60,8 +62,10 @@ import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine.Authoriza
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine.AuthorizedIndices;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine.PrivilegesCheckResult;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine.PrivilegesToCheck;
 | 
	
		
			
				|  |  | +import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.ApplicationResourcePrivileges;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges;
 | 
	
		
			
				|  |  | +import org.elasticsearch.xpack.core.security.authz.RoleDescriptorsIntersection;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.security.authz.permission.ApplicationPermission;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissions;
 | 
	
	
		
			
				|  | @@ -88,13 +92,16 @@ import org.junit.Before;
 | 
	
		
			
				|  |  |  import org.mockito.Mockito;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import java.util.ArrayList;
 | 
	
		
			
				|  |  | +import java.util.Arrays;
 | 
	
		
			
				|  |  |  import java.util.Collection;
 | 
	
		
			
				|  |  |  import java.util.Collections;
 | 
	
		
			
				|  |  |  import java.util.LinkedHashMap;
 | 
	
		
			
				|  |  |  import java.util.List;
 | 
	
		
			
				|  |  |  import java.util.Locale;
 | 
	
		
			
				|  |  | +import java.util.Objects;
 | 
	
		
			
				|  |  |  import java.util.Set;
 | 
	
		
			
				|  |  |  import java.util.TreeMap;
 | 
	
		
			
				|  |  | +import java.util.concurrent.ExecutionException;
 | 
	
		
			
				|  |  |  import java.util.stream.Collectors;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import static java.util.Collections.emptyMap;
 | 
	
	
		
			
				|  | @@ -123,6 +130,7 @@ import static org.mockito.Mockito.doThrow;
 | 
	
		
			
				|  |  |  import static org.mockito.Mockito.mock;
 | 
	
		
			
				|  |  |  import static org.mockito.Mockito.never;
 | 
	
		
			
				|  |  |  import static org.mockito.Mockito.spy;
 | 
	
		
			
				|  |  | +import static org.mockito.Mockito.times;
 | 
	
		
			
				|  |  |  import static org.mockito.Mockito.verify;
 | 
	
		
			
				|  |  |  import static org.mockito.Mockito.verifyNoMoreInteractions;
 | 
	
		
			
				|  |  |  import static org.mockito.Mockito.when;
 | 
	
	
		
			
				|  | @@ -1576,6 +1584,201 @@ public class RBACEngineTests extends ESTestCase {
 | 
	
		
			
				|  |  |          assertThat(e.getCause(), sameInstance(unsupportedOperationException));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    public void testGetRemoteAccessRoleDescriptorsIntersection() throws ExecutionException, InterruptedException {
 | 
	
		
			
				|  |  | +        assumeTrue("untrusted remote cluster feature flag must be enabled", TcpTransport.isUntrustedRemoteClusterEnabled());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final RemoteIndicesPermission.Builder remoteIndicesBuilder = RemoteIndicesPermission.builder();
 | 
	
		
			
				|  |  | +        final String concreteClusterAlias = randomAlphaOfLength(10);
 | 
	
		
			
				|  |  | +        final int numGroups = randomIntBetween(1, 3);
 | 
	
		
			
				|  |  | +        final List<IndicesPrivileges> expectedIndicesPrivileges = new ArrayList<>();
 | 
	
		
			
				|  |  | +        for (int i = 0; i < numGroups; i++) {
 | 
	
		
			
				|  |  | +            final String[] indexNames = Objects.requireNonNull(generateRandomStringArray(3, 10, false, false));
 | 
	
		
			
				|  |  | +            final boolean allowRestrictedIndices = randomBoolean();
 | 
	
		
			
				|  |  | +            final boolean hasFls = randomBoolean();
 | 
	
		
			
				|  |  | +            final FieldPermissionsDefinition.FieldGrantExcludeGroup group = hasFls
 | 
	
		
			
				|  |  | +                ? randomFieldGrantExcludeGroup()
 | 
	
		
			
				|  |  | +                : new FieldPermissionsDefinition.FieldGrantExcludeGroup(null, null);
 | 
	
		
			
				|  |  | +            final BytesReference query = randomBoolean() ? randomDlsQuery() : null;
 | 
	
		
			
				|  |  | +            final IndicesPrivileges.Builder builder = IndicesPrivileges.builder()
 | 
	
		
			
				|  |  | +                .indices(Arrays.stream(indexNames).sorted().collect(Collectors.toList()))
 | 
	
		
			
				|  |  | +                .privileges("read")
 | 
	
		
			
				|  |  | +                .allowRestrictedIndices(allowRestrictedIndices)
 | 
	
		
			
				|  |  | +                .query(query);
 | 
	
		
			
				|  |  | +            if (hasFls) {
 | 
	
		
			
				|  |  | +                builder.grantedFields(group.getGrantedFields());
 | 
	
		
			
				|  |  | +                builder.deniedFields(group.getExcludedFields());
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            expectedIndicesPrivileges.add(builder.build());
 | 
	
		
			
				|  |  | +            remoteIndicesBuilder.addGroup(
 | 
	
		
			
				|  |  | +                Set.of(randomFrom(concreteClusterAlias, "*")),
 | 
	
		
			
				|  |  | +                IndexPrivilege.READ,
 | 
	
		
			
				|  |  | +                new FieldPermissions(new FieldPermissionsDefinition(Set.of(group))),
 | 
	
		
			
				|  |  | +                query == null ? null : Set.of(query),
 | 
	
		
			
				|  |  | +                allowRestrictedIndices,
 | 
	
		
			
				|  |  | +                indexNames
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        final String mismatchedConcreteClusterAlias = randomValueOtherThan(concreteClusterAlias, () -> randomAlphaOfLength(10));
 | 
	
		
			
				|  |  | +        // Add some groups that don't match the alias
 | 
	
		
			
				|  |  | +        final int numMismatchedGroups = randomIntBetween(0, 3);
 | 
	
		
			
				|  |  | +        for (int i = 0; i < numMismatchedGroups; i++) {
 | 
	
		
			
				|  |  | +            remoteIndicesBuilder.addGroup(
 | 
	
		
			
				|  |  | +                Set.of(mismatchedConcreteClusterAlias),
 | 
	
		
			
				|  |  | +                IndexPrivilege.READ,
 | 
	
		
			
				|  |  | +                new FieldPermissions(
 | 
	
		
			
				|  |  | +                    new FieldPermissionsDefinition(Set.of(new FieldPermissionsDefinition.FieldGrantExcludeGroup(null, null)))
 | 
	
		
			
				|  |  | +                ),
 | 
	
		
			
				|  |  | +                null,
 | 
	
		
			
				|  |  | +                randomBoolean(),
 | 
	
		
			
				|  |  | +                generateRandomStringArray(3, 10, false, false)
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final Role role = mockRoleWithRemoteIndices(remoteIndicesBuilder.build());
 | 
	
		
			
				|  |  | +        final RBACAuthorizationInfo authorizationInfo = mock(RBACAuthorizationInfo.class);
 | 
	
		
			
				|  |  | +        when(authorizationInfo.getRole()).thenReturn(role);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final PlainActionFuture<RoleDescriptorsIntersection> future = new PlainActionFuture<>();
 | 
	
		
			
				|  |  | +        engine.getRemoteAccessRoleDescriptorsIntersection(concreteClusterAlias, authorizationInfo, future);
 | 
	
		
			
				|  |  | +        final RoleDescriptorsIntersection actual = future.get();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertThat(
 | 
	
		
			
				|  |  | +            actual,
 | 
	
		
			
				|  |  | +            equalTo(
 | 
	
		
			
				|  |  | +                new RoleDescriptorsIntersection(
 | 
	
		
			
				|  |  | +                    List.of(
 | 
	
		
			
				|  |  | +                        Set.of(
 | 
	
		
			
				|  |  | +                            new RoleDescriptor(
 | 
	
		
			
				|  |  | +                                RBACEngine.REMOTE_USER_ROLE_NAME,
 | 
	
		
			
				|  |  | +                                null,
 | 
	
		
			
				|  |  | +                                expectedIndicesPrivileges.stream().sorted().toArray(RoleDescriptor.IndicesPrivileges[]::new),
 | 
	
		
			
				|  |  | +                                null,
 | 
	
		
			
				|  |  | +                                null,
 | 
	
		
			
				|  |  | +                                null,
 | 
	
		
			
				|  |  | +                                null,
 | 
	
		
			
				|  |  | +                                null
 | 
	
		
			
				|  |  | +                            )
 | 
	
		
			
				|  |  | +                        )
 | 
	
		
			
				|  |  | +                    )
 | 
	
		
			
				|  |  | +                )
 | 
	
		
			
				|  |  | +            )
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        verify(role, times(1)).remoteIndices();
 | 
	
		
			
				|  |  | +        verifyNoMoreInteractions(role);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testGetRemoteAccessRoleDescriptorsIntersectionHasDeterministicOrderForIndicesPrivileges() throws ExecutionException,
 | 
	
		
			
				|  |  | +        InterruptedException {
 | 
	
		
			
				|  |  | +        assumeTrue("untrusted remote cluster feature flag must be enabled", TcpTransport.isUntrustedRemoteClusterEnabled());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final RemoteIndicesPermission.Builder remoteIndicesBuilder = RemoteIndicesPermission.builder();
 | 
	
		
			
				|  |  | +        final String concreteClusterAlias = randomAlphaOfLength(10);
 | 
	
		
			
				|  |  | +        final int numGroups = randomIntBetween(2, 5);
 | 
	
		
			
				|  |  | +        for (int i = 0; i < numGroups; i++) {
 | 
	
		
			
				|  |  | +            remoteIndicesBuilder.addGroup(
 | 
	
		
			
				|  |  | +                Set.copyOf(randomNonEmptySubsetOf(List.of(concreteClusterAlias, "*"))),
 | 
	
		
			
				|  |  | +                IndexPrivilege.get(Set.copyOf(randomSubsetOf(randomIntBetween(1, 4), IndexPrivilege.names()))),
 | 
	
		
			
				|  |  | +                new FieldPermissions(
 | 
	
		
			
				|  |  | +                    new FieldPermissionsDefinition(
 | 
	
		
			
				|  |  | +                        Set.of(
 | 
	
		
			
				|  |  | +                            randomBoolean()
 | 
	
		
			
				|  |  | +                                ? randomFieldGrantExcludeGroup()
 | 
	
		
			
				|  |  | +                                : new FieldPermissionsDefinition.FieldGrantExcludeGroup(null, null)
 | 
	
		
			
				|  |  | +                        )
 | 
	
		
			
				|  |  | +                    )
 | 
	
		
			
				|  |  | +                ),
 | 
	
		
			
				|  |  | +                randomBoolean() ? Set.of(randomDlsQuery()) : null,
 | 
	
		
			
				|  |  | +                randomBoolean(),
 | 
	
		
			
				|  |  | +                generateRandomStringArray(3, 10, false, false)
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        final RemoteIndicesPermission permissions = remoteIndicesBuilder.build();
 | 
	
		
			
				|  |  | +        List<RemoteIndicesPermission.RemoteIndicesGroup> remoteIndicesGroups = permissions.remoteIndicesGroups();
 | 
	
		
			
				|  |  | +        final Role role1 = mockRoleWithRemoteIndices(permissions);
 | 
	
		
			
				|  |  | +        final RBACAuthorizationInfo authorizationInfo1 = mock(RBACAuthorizationInfo.class);
 | 
	
		
			
				|  |  | +        when(authorizationInfo1.getRole()).thenReturn(role1);
 | 
	
		
			
				|  |  | +        final PlainActionFuture<RoleDescriptorsIntersection> future1 = new PlainActionFuture<>();
 | 
	
		
			
				|  |  | +        engine.getRemoteAccessRoleDescriptorsIntersection(concreteClusterAlias, authorizationInfo1, future1);
 | 
	
		
			
				|  |  | +        final RoleDescriptorsIntersection actual1 = future1.get();
 | 
	
		
			
				|  |  | +        verify(role1, times(1)).remoteIndices();
 | 
	
		
			
				|  |  | +        verifyNoMoreInteractions(role1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Randomize the order of both remote indices groups and each of the indices permissions groups each group holds
 | 
	
		
			
				|  |  | +        final RemoteIndicesPermission shuffledPermissions = new RemoteIndicesPermission(
 | 
	
		
			
				|  |  | +            shuffledList(
 | 
	
		
			
				|  |  | +                remoteIndicesGroups.stream()
 | 
	
		
			
				|  |  | +                    .map(
 | 
	
		
			
				|  |  | +                        group -> new RemoteIndicesPermission.RemoteIndicesGroup(
 | 
	
		
			
				|  |  | +                            group.remoteClusterAliases(),
 | 
	
		
			
				|  |  | +                            shuffledList(group.indicesPermissionGroups())
 | 
	
		
			
				|  |  | +                        )
 | 
	
		
			
				|  |  | +                    )
 | 
	
		
			
				|  |  | +                    .toList()
 | 
	
		
			
				|  |  | +            )
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        final Role role2 = mockRoleWithRemoteIndices(shuffledPermissions);
 | 
	
		
			
				|  |  | +        final RBACAuthorizationInfo authorizationInfo2 = mock(RBACAuthorizationInfo.class);
 | 
	
		
			
				|  |  | +        when(authorizationInfo2.getRole()).thenReturn(role2);
 | 
	
		
			
				|  |  | +        final PlainActionFuture<RoleDescriptorsIntersection> future2 = new PlainActionFuture<>();
 | 
	
		
			
				|  |  | +        engine.getRemoteAccessRoleDescriptorsIntersection(concreteClusterAlias, authorizationInfo2, future2);
 | 
	
		
			
				|  |  | +        final RoleDescriptorsIntersection actual2 = future2.get();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        verify(role2, times(1)).remoteIndices();
 | 
	
		
			
				|  |  | +        verifyNoMoreInteractions(role2);
 | 
	
		
			
				|  |  | +        assertThat(actual1, equalTo(actual2));
 | 
	
		
			
				|  |  | +        assertThat(actual1.roleDescriptorsList().iterator().next().iterator().next().getIndicesPrivileges().length, equalTo(numGroups));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testGetRemoteAccessRoleDescriptorsIntersectionWithoutMatchingGroups() throws ExecutionException, InterruptedException {
 | 
	
		
			
				|  |  | +        assumeTrue("untrusted remote cluster feature flag must be enabled", TcpTransport.isUntrustedRemoteClusterEnabled());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final String concreteClusterAlias = randomAlphaOfLength(10);
 | 
	
		
			
				|  |  | +        final Role role = mockRoleWithRemoteIndices(
 | 
	
		
			
				|  |  | +            RemoteIndicesPermission.builder()
 | 
	
		
			
				|  |  | +                .addGroup(
 | 
	
		
			
				|  |  | +                    Set.of(concreteClusterAlias),
 | 
	
		
			
				|  |  | +                    IndexPrivilege.READ,
 | 
	
		
			
				|  |  | +                    new FieldPermissions(new FieldPermissionsDefinition(null, null)),
 | 
	
		
			
				|  |  | +                    null,
 | 
	
		
			
				|  |  | +                    randomBoolean(),
 | 
	
		
			
				|  |  | +                    generateRandomStringArray(3, 10, false, false)
 | 
	
		
			
				|  |  | +                )
 | 
	
		
			
				|  |  | +                .build()
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        final RBACAuthorizationInfo authorizationInfo = mock(RBACAuthorizationInfo.class);
 | 
	
		
			
				|  |  | +        when(authorizationInfo.getRole()).thenReturn(role);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final PlainActionFuture<RoleDescriptorsIntersection> future = new PlainActionFuture<>();
 | 
	
		
			
				|  |  | +        engine.getRemoteAccessRoleDescriptorsIntersection(
 | 
	
		
			
				|  |  | +            randomValueOtherThan(concreteClusterAlias, () -> randomAlphaOfLength(10)),
 | 
	
		
			
				|  |  | +            authorizationInfo,
 | 
	
		
			
				|  |  | +            future
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        final RoleDescriptorsIntersection actual = future.get();
 | 
	
		
			
				|  |  | +        assertThat(actual, equalTo(RoleDescriptorsIntersection.EMPTY));
 | 
	
		
			
				|  |  | +        verify(role, times(1)).remoteIndices();
 | 
	
		
			
				|  |  | +        verifyNoMoreInteractions(role);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testGetRemoteAccessRoleDescriptorsIntersectionWithoutRemoteIndicesPermissions() throws ExecutionException,
 | 
	
		
			
				|  |  | +        InterruptedException {
 | 
	
		
			
				|  |  | +        assumeTrue("untrusted remote cluster feature flag must be enabled", TcpTransport.isUntrustedRemoteClusterEnabled());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final String concreteClusterAlias = randomAlphaOfLength(10);
 | 
	
		
			
				|  |  | +        final Role role = mockRoleWithRemoteIndices(RemoteIndicesPermission.NONE);
 | 
	
		
			
				|  |  | +        final RBACAuthorizationInfo authorizationInfo = mock(RBACAuthorizationInfo.class);
 | 
	
		
			
				|  |  | +        when(authorizationInfo.getRole()).thenReturn(role);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final PlainActionFuture<RoleDescriptorsIntersection> future = new PlainActionFuture<>();
 | 
	
		
			
				|  |  | +        engine.getRemoteAccessRoleDescriptorsIntersection(
 | 
	
		
			
				|  |  | +            randomValueOtherThan(concreteClusterAlias, () -> randomAlphaOfLength(10)),
 | 
	
		
			
				|  |  | +            authorizationInfo,
 | 
	
		
			
				|  |  | +            future
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        final RoleDescriptorsIntersection actual = future.get();
 | 
	
		
			
				|  |  | +        assertThat(actual, equalTo(RoleDescriptorsIntersection.EMPTY));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      private GetUserPrivilegesResponse.Indices findIndexPrivilege(Set<GetUserPrivilegesResponse.Indices> indices, String name) {
 | 
	
		
			
				|  |  |          return indices.stream().filter(i -> i.getIndices().contains(name)).findFirst().get();
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -1667,4 +1870,26 @@ public class RBACEngineTests extends ESTestCase {
 | 
	
		
			
				|  |  |      private static MapBuilder<String, Boolean> mapBuilder() {
 | 
	
		
			
				|  |  |          return MapBuilder.newMapBuilder();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private BytesArray randomDlsQuery() {
 | 
	
		
			
				|  |  | +        return new BytesArray(
 | 
	
		
			
				|  |  | +            "{ \"term\": { \"" + randomAlphaOfLengthBetween(3, 24) + "\" : \"" + randomAlphaOfLengthBetween(3, 24) + "\" }"
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private FieldPermissionsDefinition.FieldGrantExcludeGroup randomFieldGrantExcludeGroup() {
 | 
	
		
			
				|  |  | +        return new FieldPermissionsDefinition.FieldGrantExcludeGroup(generateRandomStringArray(3, 10, false, false), new String[] {});
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private Role mockRoleWithRemoteIndices(final RemoteIndicesPermission remoteIndicesPermission) {
 | 
	
		
			
				|  |  | +        final Role role = mock(Role.class);
 | 
	
		
			
				|  |  | +        final String[] roleNames = generateRandomStringArray(3, 10, false, false);
 | 
	
		
			
				|  |  | +        when(role.names()).thenReturn(roleNames);
 | 
	
		
			
				|  |  | +        when(role.cluster()).thenReturn(ClusterPermission.NONE);
 | 
	
		
			
				|  |  | +        when(role.indices()).thenReturn(IndicesPermission.NONE);
 | 
	
		
			
				|  |  | +        when(role.application()).thenReturn(ApplicationPermission.NONE);
 | 
	
		
			
				|  |  | +        when(role.runAs()).thenReturn(RunAsPermission.NONE);
 | 
	
		
			
				|  |  | +        when(role.remoteIndices()).thenReturn(remoteIndicesPermission);
 | 
	
		
			
				|  |  | +        return role;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 |