Skip to content

Commit

Permalink
Fix privilege requirement for CCS with Point In Time reader (#62261)
Browse files Browse the repository at this point in the history
When target indices are remote only, CCS does not require user to have privileges on the local cluster. This PR ensure Point-In-Time reader follows the same pattern.

Relates: #61827
  • Loading branch information
ywangd authored Sep 21, 2020
1 parent 7afe607 commit 4dd85a1
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.elasticsearch.transport.RemoteClusterAware;
import org.elasticsearch.transport.RemoteConnectionStrategy;
import org.elasticsearch.transport.TransportRequest;
import org.elasticsearch.xpack.core.search.action.OpenPointInTimeRequest;
import org.elasticsearch.xpack.core.security.authz.ResolvedIndices;

import java.util.ArrayList;
Expand Down Expand Up @@ -274,7 +275,8 @@ static String getPutMappingIndexOrAlias(PutMappingRequest request, List<String>

static boolean allowsRemoteIndices(IndicesRequest request) {
return request instanceof SearchRequest || request instanceof FieldCapabilitiesRequest
|| request instanceof GraphExploreRequest || request instanceof ResolveIndexAction.Request;
|| request instanceof GraphExploreRequest || request instanceof ResolveIndexAction.Request
|| request instanceof OpenPointInTimeRequest;
}

private List<String> loadAuthorizedAliases(List<String> authorizedIndices, Metadata metadata) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.common.util.concurrent.ThreadContext.StoredContext;
import org.elasticsearch.common.xcontent.XContentBuilder;
Expand All @@ -102,6 +103,10 @@
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportActionProxy;
import org.elasticsearch.transport.TransportRequest;
import org.elasticsearch.xpack.core.search.action.ClosePointInTimeAction;
import org.elasticsearch.xpack.core.search.action.ClosePointInTimeRequest;
import org.elasticsearch.xpack.core.search.action.OpenPointInTimeAction;
import org.elasticsearch.xpack.core.search.action.OpenPointInTimeRequest;
import org.elasticsearch.xpack.core.security.action.privilege.DeletePrivilegesAction;
import org.elasticsearch.xpack.core.security.action.privilege.DeletePrivilegesRequest;
import org.elasticsearch.xpack.core.security.action.user.AuthenticateAction;
Expand Down Expand Up @@ -573,6 +578,51 @@ public void testRemoteIndicesOnlyWorkWithApplicableRequestTypes() throws IOExcep
verifyNoMoreInteractions(auditTrail);
}

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[] {
hasLocalIndices ?
randomAlphaOfLength(5) :
"other_cluster:" + randomFrom(randomAlphaOfLength(5), "*", randomAlphaOfLength(4) + "*"),
"other_cluster:" + randomFrom(randomAlphaOfLength(5), "*", randomAlphaOfLength(4) + "*")
};
final OpenPointInTimeRequest openPointInTimeRequest = new OpenPointInTimeRequest(
indices, OpenPointInTimeRequest.DEFAULT_INDICES_OPTIONS, TimeValue.timeValueMinutes(randomLongBetween(1, 10)),
randomAlphaOfLength(5), randomAlphaOfLength(5)
);
if (hasLocalIndices) {
assertThrowsAuthorizationException(
() -> authorize(authentication, OpenPointInTimeAction.NAME, openPointInTimeRequest),
"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()));
} 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()));
}
verifyNoMoreInteractions(auditTrail);
}
}

public void testUserWithNoRolesCanClosePointInTime() {
final ClosePointInTimeRequest closePointInTimeRequest = new ClosePointInTimeRequest(randomAlphaOfLength(8));
final Authentication authentication = createAuthentication(new User("test user"));
mockEmptyMetadata();
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()));
verifyNoMoreInteractions(auditTrail);
}

public void testUnknownRoleCausesDenial() throws IOException {
Tuple<String, TransportRequest> tuple = randomFrom(asList(
new Tuple<>(SearchAction.NAME, new SearchRequest()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,39 @@ teardown:
close_point_in_time:
body:
id: "$pit_id"

---
"Point in time CCS with only remote indices requires no privileges on local cluster":

- do:
headers: { Authorization: "Basic cmVtb3RlOnMza3JpdA==" }
open_point_in_time:
index: "my_*:point_in_time_index"
keep_alive: 5m
- set: {id: pit_id}

- do:
headers: { Authorization: "Basic cmVtb3RlOnMza3JpdA==" }
search:
rest_total_hits_as_int: true
sort: created_at
body:
query:
range:
created_at:
gte: "2020-01-03"
pit:
id: "$pit_id"
keep_alive: 1m

- match: { hits.total: 2 }
- match: { hits.hits.0._index: "my_remote_cluster:point_in_time_index" }
- match: { hits.hits.0._source.f: "r3" }
- match: { hits.hits.1._index: "my_remote_cluster:point_in_time_index" }
- match: { hits.hits.1._source.f: "r4" }

- do:
headers: { Authorization: "Basic cmVtb3RlOnMza3JpdA==" }
close_point_in_time:
body:
id: "$pit_id"

0 comments on commit 4dd85a1

Please sign in to comment.