add the option to disable DLS and FLS completely
This commit reverts a previous change where searcher were not wrapped when the RequestContext could not be found. If DLS/FLS is enabled, which is the default, any bulk request that contains an update request will not be permitted. This change also exposes the ability to completely disable DLS and FLS so that users who are not using these features can still use bulk updates. See elastic/elasticsearch#938 Original commit: elastic/x-pack-elasticsearch@513782db1c
This commit is contained in:
parent
722bc3713e
commit
cc2096b4f9
|
@ -29,6 +29,21 @@ indices, while Elasticsearch with Shield returns exceptions. Note that this beha
|
|||
multiple items will fail the entire set of operations if any one operation throws an exception due to wildcard
|
||||
expansion resulting in an empty set of authorized indices.
|
||||
|
||||
[float]
|
||||
=== Field and Document Level Security Limitations
|
||||
|
||||
Bulk updates do not work when document and field level security is enabled. If you are not using document and field level
|
||||
security, bulk updates can be enabled by setting `shield.dls_fls.enabled` to `false`.
|
||||
|
||||
When document level security is enabled for an index:
|
||||
|
||||
* The get, multi get, termsvector and multi termsvector APIs aren't executed in real time. The realtime option for these APIs is forcefully set to false.
|
||||
* Document level security isn't applied for APIs that aren't document based. An example is the field stats API.
|
||||
* Document level security doesn't affect global index statistics that relevancy scoring uses. So this means that scores are computed without taking the role query into account.
|
||||
Note that documents not matching with the role query are never returned.
|
||||
* The `has_child` and `has_parent` queries aren't supported as role query in the `roles.yml` file.
|
||||
The `has_child` and `has_parent` queries can be used in the search API with document level security enabled.
|
||||
|
||||
[float]
|
||||
=== Document Expiration (_ttl)
|
||||
|
||||
|
|
|
@ -184,6 +184,13 @@ The parameters listed in this section are configured in the `config/elasticsearc
|
|||
| `shield.authc.anonymous.authz_exception` | `true` | When `true`, a HTTP 403 response will be returned when the anonymous user does not have the appropriate permissions for the requested action. The user will not be prompted to provide credentials to access the requested resource. When set to `false`, a HTTP 401 will be returned allowing for credentials to be provided for a user with the appropriate permissions.
|
||||
|======
|
||||
|
||||
.Shield Document and Field Level Security Settings
|
||||
[options="header"]
|
||||
|======
|
||||
| Name | Default | Description
|
||||
| `shield.dls_fls.enabled` | `true` | This setting can be used to completely disable document and field level security regardless of how roles are configured.
|
||||
|======
|
||||
|
||||
|
||||
[[ref-realm-settings]]
|
||||
|
||||
|
|
|
@ -158,14 +158,3 @@ customer_care:
|
|||
privileges: read
|
||||
query: '{"term" : {"department_id" : "12"}}''
|
||||
--------------------------------------------------
|
||||
|
||||
===== Limitations
|
||||
|
||||
When document level security is enabled for an index:
|
||||
|
||||
* The get, multi get, termsvector and multi termsvector APIs aren't executed in real time. The realtime option for these APIs is forcefully set to false.
|
||||
* Document level security isn't applied for APIs that aren't document based oriented. For example this is the case for the field stats API.
|
||||
* Document level security doesn't affect global index statistics that relevancy scoring uses. So this means that scores are computed without taking the role query into account.
|
||||
Note that documents not matching with the role query are never returned.
|
||||
* The `has_child` and `has_parent` queries aren't supported as role query in the `roles.yml` file.
|
||||
The `has_child` and `has_parent` queries can be used in the search API with document level security enabled.
|
|
@ -62,6 +62,7 @@ public class ShieldPlugin extends Plugin {
|
|||
public static final String NAME = "shield";
|
||||
public static final String ENABLED_SETTING_NAME = NAME + ".enabled";
|
||||
public static final String OPT_OUT_QUERY_CACHE = "opt_out_cache";
|
||||
public static final String DLS_FLS_ENABLED_SETTING = "shield.dls_fls.enabled";
|
||||
|
||||
private static final boolean DEFAULT_ENABLED_SETTING = true;
|
||||
|
||||
|
@ -159,9 +160,11 @@ public class ShieldPlugin extends Plugin {
|
|||
return;
|
||||
}
|
||||
assert shieldLicenseState != null;
|
||||
module.setSearcherWrapper((indexService) -> new ShieldIndexSearcherWrapper(indexService.getIndexSettings(),
|
||||
indexService.getQueryShardContext(), indexService.mapperService(),
|
||||
indexService.cache().bitsetFilterCache(), shieldLicenseState));
|
||||
if (flsDlsEnabled(settings)) {
|
||||
module.setSearcherWrapper((indexService) -> new ShieldIndexSearcherWrapper(indexService.getIndexSettings(),
|
||||
indexService.getQueryShardContext(), indexService.mapperService(),
|
||||
indexService.cache().bitsetFilterCache(), shieldLicenseState));
|
||||
}
|
||||
if (clientMode == false) {
|
||||
module.registerQueryCache(ShieldPlugin.OPT_OUT_QUERY_CACHE, OptOutQueryCache::new);
|
||||
}
|
||||
|
@ -305,6 +308,10 @@ public class ShieldPlugin extends Plugin {
|
|||
return settings.getAsBoolean(ENABLED_SETTING_NAME, DEFAULT_ENABLED_SETTING);
|
||||
}
|
||||
|
||||
public static boolean flsDlsEnabled(Settings settings) {
|
||||
return settings.getAsBoolean(DLS_FLS_ENABLED_SETTING, true);
|
||||
}
|
||||
|
||||
private void failIfShieldQueryCacheIsNotActive(Settings settings, boolean nodeSettings) {
|
||||
String queryCacheImplementation;
|
||||
if (nodeSettings) {
|
||||
|
|
|
@ -12,6 +12,8 @@ import org.elasticsearch.action.update.UpdateRequest;
|
|||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.shield.ShieldPlugin;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
|
||||
/**
|
||||
|
@ -24,11 +26,21 @@ public class BulkRequestInterceptor extends FieldSecurityRequestInterceptor<Bulk
|
|||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void intercept(BulkRequest request, User user) {
|
||||
// FIXME remove this method override once we support bulk updates with DLS and FLS enabled overall. We'll still
|
||||
// need this interceptor because individual users may still have FLS/DLS enabled and we'll want to reject only
|
||||
// their requests. Also update the message to remove "document"
|
||||
if (ShieldPlugin.flsDlsEnabled(this.settings)) {
|
||||
disableFeatures(request);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disableFeatures(BulkRequest bulkRequest) {
|
||||
for (ActionRequest actionRequest : bulkRequest.requests()) {
|
||||
if (actionRequest instanceof UpdateRequest) {
|
||||
throw new ElasticsearchSecurityException("Can't execute an bulk request with update requests embedded if field level security is enabled", RestStatus.BAD_REQUEST);
|
||||
throw new ElasticsearchSecurityException("Can't execute an bulk request with update requests embedded if document and field level security is enabled", RestStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,8 +83,8 @@ public class ShieldIndexSearcherWrapper extends IndexSearcherWrapper {
|
|||
try {
|
||||
RequestContext context = RequestContext.current();
|
||||
if (context == null) {
|
||||
logger.debug("couldn't locate the current request, field level security will not be applied");
|
||||
return reader;
|
||||
logger.debug("couldn't locate the current request, field level security will only allow meta fields");
|
||||
return FieldSubsetReader.wrap(reader, allowedMetaFields);
|
||||
}
|
||||
|
||||
IndicesAccessControl indicesAccessControl = context.getRequest().getFromContext(InternalAuthorizationService.INDICES_PERMISSIONS_KEY);
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.elasticsearch.action.get.GetResponse;
|
|||
import org.elasticsearch.action.update.UpdateResponse;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.elasticsearch.shield.ShieldPlugin;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
|
@ -29,6 +30,7 @@ public class BulkUpdateTests extends ShieldIntegTestCase {
|
|||
return Settings.builder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put(Node.HTTP_ENABLED, true)
|
||||
.put(ShieldPlugin.DLS_FLS_ENABLED_SETTING, false) //FIXME randomize once DLS/FLS works with Bulk updates...
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -775,15 +775,21 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
fail("failed, because bulk request with updates shouldn't be allowed if field level security is enabled");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST));
|
||||
assertThat(e.getMessage(), equalTo("Can't execute an bulk request with update requests embedded if field level security is enabled"));
|
||||
assertThat(e.getMessage(), equalTo("Can't execute an bulk request with update requests embedded if document and field level security is enabled"));
|
||||
}
|
||||
assertThat(client().prepareGet("test", "type", "1").get().getSource().get("field2").toString(), equalTo("value2"));
|
||||
|
||||
// FIXME this should work once we can support update requests within BulkRequests...
|
||||
// With no field level security enabled the update in bulk is allowed:
|
||||
client().prepareBulk()
|
||||
.add(new UpdateRequest("test", "type", "1").doc("field2", "value3"))
|
||||
.get();
|
||||
assertThat(client().prepareGet("test", "type", "1").get().getSource().get("field2").toString(), equalTo("value3"));
|
||||
try {
|
||||
client().prepareBulk()
|
||||
.add(new UpdateRequest("test", "type", "1").doc("field2", "value3"))
|
||||
.get();
|
||||
assertThat(client().prepareGet("test", "type", "1").get().getSource().get("field2").toString(), equalTo("value3"));
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST));
|
||||
assertThat(e.getMessage(), equalTo("Can't execute an bulk request with update requests embedded if document and field level security is enabled"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testQuery_withRoleWithFieldWildcards() throws Exception {
|
||||
|
|
Loading…
Reference in New Issue