From f92314ba0025250cbe5a23fda4c1bbf1c09ef7fe Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Wed, 15 Jun 2016 14:16:39 -0400 Subject: [PATCH] Disable field stats cache if field level security Field level security poisons that cache. Closes elastic/elasticsearch#2528 Original commit: elastic/x-pack-elasticsearch@12ca4a2ef44a8ab80621fbc6cdb3103a28fb9626 --- .../shield/action/ShieldActionModule.java | 2 ++ ...cumentLevelSecurityRequestInterceptor.java | 16 +++++---- .../FieldStatsRequestInterceptor.java | 34 +++++++++++++++++++ .../RealtimeRequestInterceptor.java | 3 +- .../interceptor/SearchRequestInterceptor.java | 2 +- .../interceptor/UpdateRequestInterceptor.java | 2 +- .../integration/FieldLevelSecurityTests.java | 1 - 7 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldStatsRequestInterceptor.java diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionModule.java index 963f35e0ea4..d54ca1b89aa 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionModule.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionModule.java @@ -9,6 +9,7 @@ import org.elasticsearch.common.inject.multibindings.Multibinder; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.shield.action.filter.ShieldActionFilter; import org.elasticsearch.shield.action.interceptor.BulkRequestInterceptor; +import org.elasticsearch.shield.action.interceptor.FieldStatsRequestInterceptor; import org.elasticsearch.shield.action.interceptor.RealtimeRequestInterceptor; import org.elasticsearch.shield.action.interceptor.RequestInterceptor; import org.elasticsearch.shield.action.interceptor.SearchRequestInterceptor; @@ -34,5 +35,6 @@ public class ShieldActionModule extends AbstractShieldModule.Node { multibinder.addBinding().to(SearchRequestInterceptor.class); multibinder.addBinding().to(UpdateRequestInterceptor.class); multibinder.addBinding().to(BulkRequestInterceptor.class); + multibinder.addBinding().to(FieldStatsRequestInterceptor.class); } } diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldAndDocumentLevelSecurityRequestInterceptor.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldAndDocumentLevelSecurityRequestInterceptor.java index d8cdd452c93..b53faa521cf 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldAndDocumentLevelSecurityRequestInterceptor.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldAndDocumentLevelSecurityRequestInterceptor.java @@ -47,12 +47,14 @@ public abstract class FieldAndDocumentLevelSecurityRequestInterceptor e for (String index : indicesRequest.indices()) { IndicesAccessControl.IndexAccessControl indexAccessControl = indicesAccessControl.getIndexPermissions(index); if (indexAccessControl != null) { - boolean fls = indexAccessControl.getFields() != null; - boolean dls = indexAccessControl.getQueries() != null; - if (fls || dls) { - logger.debug("intercepted request for index [{}] with field level or document level security enabled, " + - "disabling features", index); - disableFeatures(request); + boolean fieldLevelSecurityEnabled = indexAccessControl.getFields() != null; + boolean documentLevelSecurityEnabled = indexAccessControl.getQueries() != null; + if (fieldLevelSecurityEnabled || documentLevelSecurityEnabled) { + if (logger.isDebugEnabled()) { + logger.debug("intercepted request for index [{}] with field level [{}] or document level [{}] security " + + "enabled, disabling features", index, fieldLevelSecurityEnabled, documentLevelSecurityEnabled); + } + disableFeatures(request, fieldLevelSecurityEnabled, documentLevelSecurityEnabled); return; } } @@ -62,6 +64,6 @@ public abstract class FieldAndDocumentLevelSecurityRequestInterceptor e } } - protected abstract void disableFeatures(Request request); + protected abstract void disableFeatures(Request request, boolean fieldLevelSecurityEnabled, boolean documentLevelSecurityEnabled); } diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldStatsRequestInterceptor.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldStatsRequestInterceptor.java new file mode 100644 index 00000000000..46edc92b18a --- /dev/null +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldStatsRequestInterceptor.java @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.shield.action.interceptor; + +import org.elasticsearch.action.fieldstats.FieldStatsRequest; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.transport.TransportRequest; + +/** + * Intercepts requests to shards to field level stats and strips fields that the user is not allowed to access from the response. + */ +public class FieldStatsRequestInterceptor extends FieldAndDocumentLevelSecurityRequestInterceptor { + @Inject + public FieldStatsRequestInterceptor(Settings settings, ThreadPool threadPool) { + super(settings, threadPool.getThreadContext()); + } + + @Override + public boolean supports(TransportRequest request) { + return request instanceof FieldStatsRequest; + } + + @Override + protected void disableFeatures(FieldStatsRequest request, boolean fieldLevelSecurityEnabled, boolean documentLevelSecurityEnabled) { + if (fieldLevelSecurityEnabled) { + request.setUseCache(false); + } + } +} diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/RealtimeRequestInterceptor.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/RealtimeRequestInterceptor.java index df0ac5f1e44..7dca9937319 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/RealtimeRequestInterceptor.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/RealtimeRequestInterceptor.java @@ -23,7 +23,8 @@ public class RealtimeRequestInterceptor extends FieldAndDocumentLevelSecurityReq } @Override - protected void disableFeatures(RealtimeRequest realtimeRequest) { + protected void disableFeatures(RealtimeRequest realtimeRequest, boolean fieldLevelSecurityEnabled, + boolean documentLevelSecurityEnabled) { realtimeRequest.realtime(false); } diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/SearchRequestInterceptor.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/SearchRequestInterceptor.java index 51afa39f1c0..168ce041885 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/SearchRequestInterceptor.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/SearchRequestInterceptor.java @@ -22,7 +22,7 @@ public class SearchRequestInterceptor extends FieldAndDocumentLevelSecurityReque } @Override - public void disableFeatures(SearchRequest request) { + public void disableFeatures(SearchRequest request, boolean fieldLevelSecurityEnabled, boolean documentLevelSecurityEnabled) { request.requestCache(false); } diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/UpdateRequestInterceptor.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/UpdateRequestInterceptor.java index 88a7cf424ba..1800265b666 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/UpdateRequestInterceptor.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/UpdateRequestInterceptor.java @@ -28,7 +28,7 @@ public class UpdateRequestInterceptor extends FieldAndDocumentLevelSecurityReque } @Override - protected void disableFeatures(UpdateRequest updateRequest) { + protected void disableFeatures(UpdateRequest updateRequest, boolean fieldLevelSecurityEnabled, boolean documentLevelSecurityEnabled) { throw new ElasticsearchSecurityException("Can't execute an update request if field or document level security is enabled", RestStatus.BAD_REQUEST); } diff --git a/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityTests.java index 06a54d43277..64c9a08bdbe 100644 --- a/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityTests.java @@ -483,7 +483,6 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase { assertThat(response.getResponses()[0].getResponse().getSource().get("field2").toString(), equalTo("value2")); } - @AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/2528") public void testFieldStatsApi() throws Exception { assertAcked(client().admin().indices().prepareCreate("test") .addMapping("type1", "field1", "type=text", "field2", "type=text", "field3", "type=text")