- Notifications
You must be signed in to change notification settings - Fork 25.6k
Reuse FieldPermissionsCache in Role parsing #94931
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
Changes from 2 commits
e2c3cb9 6e08ce7 06fe78a 3bcc7e4 cccf6b9 f0d7487 9349591 320c472 c3e11e1 c0e0feb b8727e5 File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| pr: 94931 | ||
| summary: Reuse `FieldPermissionsCache` in Role parsing | ||
| area: Authorization | ||
| type: enhancement | ||
| issues: [] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| | @@ -6,6 +6,7 @@ | |
| */ | ||
| package org.elasticsearch.xpack.core.security.authz.permission; | ||
| | ||
| import org.apache.lucene.util.SetOnce; | ||
| import org.apache.lucene.util.automaton.Automaton; | ||
| import org.elasticsearch.ElasticsearchException; | ||
| import org.elasticsearch.common.cache.Cache; | ||
| | @@ -33,6 +34,8 @@ | |
| */ | ||
| public final class FieldPermissionsCache { | ||
| | ||
| private static final SetOnce<FieldPermissionsCache> INSTANCE = new SetOnce<>(); | ||
| | ||
| public static final Setting<Long> CACHE_SIZE_SETTING = Setting.longSetting( | ||
| setting("authz.store.roles.field_permissions.cache.max_size_in_bytes"), | ||
| 100 * 1024 * 1024, | ||
| | @@ -41,13 +44,37 @@ public final class FieldPermissionsCache { | |
| ); | ||
| private final Cache<FieldPermissionsDefinition, FieldPermissions> cache; | ||
| | ||
| public static FieldPermissionsCache init(Settings settings) { | ||
| final FieldPermissionsCache cache = new FieldPermissionsCache(settings); | ||
| INSTANCE.set(cache); | ||
| return cache; | ||
| } | ||
| | ||
| public static FieldPermissionsCache getCache() { | ||
| return INSTANCE.get(); | ||
| } | ||
| | ||
| public Cache.CacheStats getCacheStats() { | ||
| return cache.stats(); | ||
| } | ||
| | ||
| public FieldPermissionsCache(Settings settings) { | ||
| this.cache = CacheBuilder.<FieldPermissionsDefinition, FieldPermissions>builder() | ||
| .setMaximumWeight(CACHE_SIZE_SETTING.get(settings)) | ||
| .weigher((key, fieldPermissions) -> fieldPermissions.ramBytesUsed()) | ||
| .build(); | ||
| } | ||
| | ||
| public static FieldPermissions resolve(String[] grantedFields, String[] deniedFields) { | ||
| final FieldPermissionsDefinition definition = new FieldPermissionsDefinition(grantedFields, deniedFields); | ||
| final FieldPermissionsCache cache = INSTANCE.get(); | ||
| if (cache == null) { | ||
| return new FieldPermissions(definition); | ||
| ||
| } else { | ||
| return cache.getFieldPermissions(definition); | ||
| } | ||
| } | ||
| | ||
| /** | ||
| * Gets a {@link FieldPermissions} instance that corresponds to the granted and denied parameters. The instance may come from the cache | ||
| * or if it gets created, the instance will be cached | ||
| | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| | @@ -742,7 +742,7 @@ Collection<Object> createComponents( | |
| components.add(privilegeStore); | ||
| | ||
| dlsBitsetCache.set(new DocumentSubsetBitsetCache(settings, threadPool)); | ||
| final FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(settings); | ||
| final FieldPermissionsCache fieldPermissionsCache = FieldPermissionsCache.init(settings); | ||
| final FileRolesStore fileRolesStore = new FileRolesStore( | ||
| settings, | ||
| environment, | ||
| | @@ -910,6 +910,7 @@ Collection<Object> createComponents( | |
| final AuthorizationService authzService = new AuthorizationService( | ||
| settings, | ||
| allRolesStore, | ||
| fieldPermissionsCache, | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to make this change? The cache used by RBACEngine is techinically cross different index groups and the combination depends on the requested indices patterns, e.g. if we have If the requested index pattern is While the cache used in CompositeRolesStore is most likely keyed by a single index group. With the above example, the two groups will be cached separately. If we combine the two caches, it is possible that more entries would be competing for cache usages. Along the same line of reasoning, the cache used by RoleDescriptor is purely for a single index definition. Strictly speaking, it can also be different from the cache usage by CompositeRolesStore which can combine index groups if they have exactly the same In summary, the cache is keyed slightly different with the 3 use cases:
That said, I do think having a single cache for them is reasonable because we don't really want to differentiate clearly between the different type of cache keys. My only concern is whether combining them could add extra noticeable pressure on this single cache. | ||
| clusterService, | ||
| auditTrailService, | ||
| failureHandler, | ||
| | ||
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 feels a bit odd to have both a staticly shared instance and a public constructor.