-
Notifications
You must be signed in to change notification settings - Fork 24.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support shard request cache for queries with DLS and FLS #70191
Conversation
Historically we have disabled the shard request cache when FLS/DLS is enabled. This commit changes the behaviour so that caching is enabled, but takes into account the FLS/DLS context of the request.
server/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java
Outdated
Show resolved
Hide resolved
.../java/org/elasticsearch/xpack/core/security/authz/permission/FieldPermissionsDefinition.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for tackling this @ywangd . I left a comment on how we plug the cache modifier. I think we can make it cleaner with a clear extension in our plugins.
server/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java
Outdated
Show resolved
Hide resolved
server/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ywangd Thanks for PR! Exciting development! Nice to see a progress on this! Your approach looks simple and understandable to me. But I wonder if what Jim suggested is a more clean way.
How does this work with aliases? For example, two aliases pointing to the same concrete index but have different DLS/FLS applied to them.
Wouldn't bytes in ShardSearchRequest.cacheModifier
be different in this case for each different alias?
...c/main/java/org/elasticsearch/xpack/security/authz/interceptor/SearchRequestInterceptor.java
Outdated
Show resolved
Hide resolved
...n/java/org/elasticsearch/xpack/security/authz/interceptor/ShardSearchRequestInterceptor.java
Outdated
Show resolved
Hide resolved
@elasticmachine update branch |
@jimczi I updated the PR based on your suggestion of adding a new SearchPlugin extension point. A new class, DlsFlsRequestCacheDifferentiator, is added to support this new extension point. Its code logic is largely a copy/paste from the |
I just realised a BWC implication with the approach of SearchPlugin extesion point. The extesion works by hook into the cacheKey computation process without changing the
Senario 3 basically says that we cannot backport changes of this PR into |
For non-CCS cases you should be able to work around this with a simple check on the ClusterState ( I'm not sure how easy it is to do the same for CCS, but we can work something out. |
Right. I just had another thought on it and found out scenario 3 is not specific to the search plugin extension approach. The same thing can happen with the original approach of adding a I'll comment on the CCS in a separate channel. |
@tvernum I have updated the PR as discussed, i.e. disable caching for stored script, but otherwise building the cache key using the evaluated script result. The main changes are in |
...rc/main/java/org/elasticsearch/xpack/core/security/authz/permission/DocumentPermissions.java
Outdated
Show resolved
Hide resolved
public void buildCacheKey(StreamOutput out) throws IOException { | ||
assert false == (queries == null && limitedByQueries == null) : "one of queries and limited-by queries must be non-null"; | ||
if (queries != null) { | ||
assert evaluatedQueries != null : "queries are not evaluated"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels wrong. It means that it's only possible to call this method if you have called some other method first.
But in fact there's no reason for the caller to know that they should do that, or to even expect them to be linked.
It might be what we need to do right now, but I'm very reluctant to leave it this way.
The obvious answers are to either:
- Inject enough services into the constructor (or a builder) to evaluate the queries immediately
- Split this class into 2, so that there's a separate
EvaluatedDocumentPermissions
class that implementsCacheKey
.
I don't know if either of those are feasible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's certainly non-ideal. But it is not really feasible to go with either of your options either. I thought about first one but it's cascading changes all over the place and it is questionable to inject ScriptService
everywhere. The second option does not completely get rid of the "your must call some other method first" problem. It just moves it to a different place.
I had another idea initially but didn't go with it. But maybe it is a better approach after all: We can modify the buildCacheKey
signature to take User
and ScriptService
. They are not really needed at code level in most places and entirely not needed in practice, that's why I didn't go with it because they seem to be superfluous and I was considering the problem you raised to be less of an issue (e.g. some object needs to be init
after instantiation to be really usable). It's a balancing act, right now I am OK with either one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed, we agree to change the signature of buildCacheKey
to pass in a DlsQueryEvaluationContext
. Overall this change is the least intrusive.
...src/main/java/org/elasticsearch/xpack/core/security/authz/support/DLSRoleQueryValidator.java
Outdated
Show resolved
Hide resolved
Shard level request cache is now generally supported for queries with DLS and/or FLS. The request cache is now enabled following the same rule as a regular search w/o DLS/FLS except following few scenarios where the request cache will still be disabled: 1. DLS query uses a stored script 2. The search targets any remote indices 3. The cluster has any nodes older than v7.11.2 It is worth noting that the caching behaviour is overall safety over efficiency. This means two functional equivalent set of DLS or FLS permissions can possibly result into different cache entries. We consider this a better tradeoff due to higher priorities for correctness and security.
…4618) Shard level request cache is now generally supported for queries with DLS and/or FLS. The request cache is now enabled following the same rule as a regular search w/o DLS/FLS except following few scenarios where the request cache will still be disabled: 1. DLS query uses a stored script 2. The search targets any remote indices 3. The cluster has any nodes older than v7.11.2 It is worth noting that the caching behaviour is overall safety over efficiency. This means two functional equivalent set of DLS or FLS permissions can possibly result into different cache entries. We consider this a better tradeoff due to higher priorities for correctness and security.
The test can now be re-enabled since the changes from elastic#70191 are now backported.
Shard level request cache is now generally supported after elastic#70191
Shard level request cache is now generally supported after #70191 This PR updates the security limitation to state the effect.
Shard level request cache is now generally supported after elastic#70191 This PR updates the security limitation to state the effect.
Shard level request cache is now generally supported after elastic#70191 This PR updates the security limitation to state the effect.
Shard level request cache is now generally supported after elastic#70191 This PR updates the security limitation to state the effect.
Today the shard request cache is disabled by RequestInterceptor when it detects any DLS/FLS is involved in the query. We'd like to enable the cache with changes proposed by this PR. This is labelled as "draft" because we would like to validate the overall approach first before polishing it. In a nutshell, the changes are as the follows:
cacheModifier
field toShardSearchRequest
.ShardSearchRequestInterceptor
sets the value ofcacheModifier
by essentially serialising the DLS queries and FLS field definitions.cacheModifier
field becomes part of theShardSearchRequeset#cacheKey
method. Hence two otherwise identical queries will be cached with different keys if theircacheModifiers
are different.@tvernum came up with the overall idea and did most of the code changes. I have only done some tweaks so far. But I'll keep working on it and see it through (if we agree on the proposed changes).
Since this is just a draft, there are many things we glossed over. Other than tests and docs, here are a few things that we talked about didn't have time to work on:
Resolves: #44581