Authorize on shard requests for bulk actions (elastic/x-pack-elasticsearch#2369)
* Add support for authz checks at on shard requests * Add Rest Tests for authorization * Bulk security - Only reject individual items, rather than a whole shard * Sync with core change * Grant "delete" priv in ML smoketest This role had index and+bulk privileges but it also needs delete (in order to delete ML model-snapshots) Original commit: elastic/x-pack-elasticsearch@830e89e652
This commit is contained in:
parent
2033b027ed
commit
57a07d6b5a
|
@ -15,12 +15,15 @@ import java.util.function.Predicate;
|
|||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.CompositeIndicesRequest;
|
||||
import org.elasticsearch.action.DocWriteRequest;
|
||||
import org.elasticsearch.action.IndicesRequest;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthAction;
|
||||
import org.elasticsearch.action.admin.indices.alias.Alias;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
||||
import org.elasticsearch.action.bulk.BulkAction;
|
||||
import org.elasticsearch.action.bulk.BulkItemRequest;
|
||||
import org.elasticsearch.action.bulk.BulkShardRequest;
|
||||
import org.elasticsearch.action.bulk.TransportShardBulkAction;
|
||||
import org.elasticsearch.action.delete.DeleteAction;
|
||||
import org.elasticsearch.action.get.MultiGetAction;
|
||||
import org.elasticsearch.action.index.IndexAction;
|
||||
|
@ -30,6 +33,7 @@ import org.elasticsearch.action.search.SearchScrollAction;
|
|||
import org.elasticsearch.action.search.SearchTransportService;
|
||||
import org.elasticsearch.action.support.replication.TransportReplicationAction.ConcreteShardRequest;
|
||||
import org.elasticsearch.action.termvectors.MultiTermVectorsAction;
|
||||
import org.elasticsearch.action.update.UpdateAction;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
|
@ -62,7 +66,6 @@ import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
|
|||
import org.elasticsearch.xpack.security.authz.store.ReservedRolesStore;
|
||||
import org.elasticsearch.xpack.security.support.Automatons;
|
||||
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
||||
import org.elasticsearch.xpack.security.user.ElasticUser;
|
||||
import org.elasticsearch.xpack.security.user.SystemUser;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
import org.elasticsearch.xpack.security.user.XPackUser;
|
||||
|
@ -118,10 +121,10 @@ public class AuthorizationService extends AbstractComponent {
|
|||
* have the appropriate privileges for this action/request, an {@link ElasticsearchSecurityException}
|
||||
* will be thrown.
|
||||
*
|
||||
* @param authentication The authentication information
|
||||
* @param action The action
|
||||
* @param request The request
|
||||
* @throws ElasticsearchSecurityException If the given user is no allowed to execute the given request
|
||||
* @param authentication The authentication information
|
||||
* @param action The action
|
||||
* @param request The request
|
||||
* @throws ElasticsearchSecurityException If the given user is no allowed to execute the given request
|
||||
*/
|
||||
public void authorize(Authentication authentication, String action, TransportRequest request, Role userRole,
|
||||
Role runAsRole) throws ElasticsearchSecurityException {
|
||||
|
@ -208,7 +211,7 @@ public class AuthorizationService extends AbstractComponent {
|
|||
throw denial(authentication, action, request);
|
||||
} else if (TransportActionProxy.isProxyAction(action)) {
|
||||
// we authorize proxied actions once they are "unwrapped" on the next node
|
||||
if (TransportActionProxy.isProxyRequest(originalRequest) == false ) {
|
||||
if (TransportActionProxy.isProxyRequest(originalRequest) == false) {
|
||||
throw new IllegalStateException("originalRequest is not a proxy request: [" + originalRequest + "] but action: ["
|
||||
+ action + "] is a proxy action");
|
||||
}
|
||||
|
@ -317,9 +320,45 @@ public class AuthorizationService extends AbstractComponent {
|
|||
}
|
||||
}
|
||||
|
||||
if (action.equals(TransportShardBulkAction.ACTION_NAME)) {
|
||||
// is this is performing multiple actions on the index, then check each of those actions.
|
||||
assert request instanceof BulkShardRequest
|
||||
: "Action " + action + " requires " + BulkShardRequest.class + " but was " + request.getClass();
|
||||
|
||||
if (localIndices.size() != 1) {
|
||||
throw new IllegalStateException("Action " + action + " should operate on exactly 1 local index but was "
|
||||
+ localIndices.size());
|
||||
}
|
||||
|
||||
String index = localIndices.iterator().next();
|
||||
BulkShardRequest bulk = (BulkShardRequest) request;
|
||||
for (BulkItemRequest item : bulk.items()) {
|
||||
final String itemAction = getAction(item);
|
||||
final IndicesAccessControl itemAccessControl = permission.authorize(itemAction, localIndices, metaData,
|
||||
fieldPermissionsCache);
|
||||
if (itemAccessControl.isGranted() == false) {
|
||||
item.abort(index, denial(authentication, itemAction, request));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grant(authentication, action, originalRequest);
|
||||
}
|
||||
|
||||
private String getAction(BulkItemRequest item) {
|
||||
final DocWriteRequest docWriteRequest = item.request();
|
||||
switch (docWriteRequest.opType()) {
|
||||
case INDEX:
|
||||
case CREATE:
|
||||
return IndexAction.NAME;
|
||||
case UPDATE:
|
||||
return UpdateAction.NAME;
|
||||
case DELETE:
|
||||
return DeleteAction.NAME;
|
||||
}
|
||||
throw new IllegalArgumentException("No equivalent action for opType [" + docWriteRequest.opType() + "]");
|
||||
}
|
||||
|
||||
private ResolvedIndices resolveIndexNames(Authentication authentication, String action, TransportRequest request, MetaData metaData,
|
||||
AuthorizedIndices authorizedIndices) {
|
||||
try {
|
||||
|
|
|
@ -12,11 +12,13 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.CompositeIndicesRequest;
|
||||
import org.elasticsearch.action.DocWriteRequest;
|
||||
import org.elasticsearch.action.MockIndicesRequest;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthAction;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
|
||||
|
@ -49,9 +51,9 @@ import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequest;
|
|||
import org.elasticsearch.action.admin.indices.upgrade.get.UpgradeStatusAction;
|
||||
import org.elasticsearch.action.admin.indices.upgrade.get.UpgradeStatusRequest;
|
||||
import org.elasticsearch.action.bulk.BulkAction;
|
||||
import org.elasticsearch.action.bulk.BulkItemRequest;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.action.bulk.BulkShardRequest;
|
||||
import org.elasticsearch.action.delete.DeleteAction;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
import org.elasticsearch.action.get.GetAction;
|
||||
|
@ -71,6 +73,7 @@ import org.elasticsearch.action.search.SearchScrollRequest;
|
|||
import org.elasticsearch.action.search.SearchTransportService;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.action.support.PlainActionFuture;
|
||||
import org.elasticsearch.action.support.WriteRequest;
|
||||
import org.elasticsearch.action.termvectors.MultiTermVectorsAction;
|
||||
import org.elasticsearch.action.termvectors.MultiTermVectorsRequest;
|
||||
import org.elasticsearch.action.termvectors.TermVectorsAction;
|
||||
|
@ -81,13 +84,16 @@ import org.elasticsearch.client.Client;
|
|||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.TriFunction;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.index.IndexNotFoundException;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.license.GetLicenseAction;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
@ -724,11 +730,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
List<Tuple<String, TransportRequest>> requests = new ArrayList<>();
|
||||
requests.add(new Tuple<>(DeleteAction.NAME, new DeleteRequest(SecurityLifecycleService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(BulkAction.NAME + "[s]",
|
||||
new DeleteRequest(SecurityLifecycleService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
createBulkShardRequest(SecurityLifecycleService.SECURITY_INDEX_NAME, DeleteRequest::new)));
|
||||
requests.add(new Tuple<>(UpdateAction.NAME, new UpdateRequest(SecurityLifecycleService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(IndexAction.NAME, new IndexRequest(SecurityLifecycleService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(BulkAction.NAME + "[s]", new IndexRequest(SecurityLifecycleService.SECURITY_INDEX_NAME,
|
||||
"type", "id")));
|
||||
requests.add(new Tuple<>(BulkAction.NAME + "[s]",
|
||||
createBulkShardRequest(SecurityLifecycleService.SECURITY_INDEX_NAME, IndexRequest::new)));
|
||||
requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(SecurityLifecycleService.SECURITY_INDEX_NAME)));
|
||||
requests.add(new Tuple<>(TermVectorsAction.NAME,
|
||||
new TermVectorsRequest(SecurityLifecycleService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
|
@ -854,30 +860,36 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testCompositeActionsIndicesAreCheckedAtTheShardLevel() {
|
||||
String action;
|
||||
switch(randomIntBetween(0, 4)) {
|
||||
final MockIndicesRequest mockRequest = new MockIndicesRequest(IndicesOptions.strictExpandOpen(), "index");
|
||||
final TransportRequest request;
|
||||
final String action;
|
||||
switch (randomIntBetween(0, 4)) {
|
||||
case 0:
|
||||
action = MultiGetAction.NAME + "[shard]";
|
||||
request = mockRequest;
|
||||
break;
|
||||
case 1:
|
||||
//reindex, msearch, search template, and multi search template delegate to search
|
||||
action = SearchAction.NAME;
|
||||
request = mockRequest;
|
||||
break;
|
||||
case 2:
|
||||
action = MultiTermVectorsAction.NAME + "[shard]";
|
||||
request = mockRequest;
|
||||
break;
|
||||
case 3:
|
||||
action = BulkAction.NAME + "[s]";
|
||||
request = createBulkShardRequest("index", IndexRequest::new);
|
||||
break;
|
||||
case 4:
|
||||
action = "indices:data/read/mpercolate[s]";
|
||||
request = mockRequest;
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
logger.info("--> action: {}", action);
|
||||
|
||||
TransportRequest request = new MockIndicesRequest(IndicesOptions.strictExpandOpen(), "index");
|
||||
User userAllowed = new User("userAllowed", "roleAllowed");
|
||||
roleMap.put("roleAllowed", new RoleDescriptor("roleAllowed", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("index").privileges("all").build() }, null));
|
||||
|
@ -890,6 +902,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
() -> authorize(createAuthentication(userDenied), action, request), action, "userDenied");
|
||||
}
|
||||
|
||||
private BulkShardRequest createBulkShardRequest(String indexName, TriFunction<String, String, String, DocWriteRequest<?>> req) {
|
||||
final BulkItemRequest[] items = { new BulkItemRequest(1, req.apply(indexName, "type", "id")) };
|
||||
return new BulkShardRequest(new ShardId(indexName, UUID.randomUUID().toString(), 1), WriteRequest.RefreshPolicy.IMMEDIATE, items);
|
||||
}
|
||||
|
||||
public void testSameUserPermission() {
|
||||
final User user = new User("joe");
|
||||
final boolean changePasswordRequest = randomBoolean();
|
||||
|
|
|
@ -0,0 +1,257 @@
|
|||
---
|
||||
setup:
|
||||
- skip:
|
||||
features: headers
|
||||
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
xpack.security.put_role:
|
||||
name: "mixed_role"
|
||||
body: >
|
||||
{
|
||||
"indices": [
|
||||
{ "names": ["only_read"], "privileges": ["read"] },
|
||||
{ "names": ["only_index"], "privileges": ["index"] },
|
||||
{ "names": ["only_delete"], "privileges": ["delete"] },
|
||||
{ "names": ["everything"], "privileges": ["all"] }
|
||||
]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.security.put_user:
|
||||
username: "test_user"
|
||||
body: >
|
||||
{
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : [ "mixed_role" ],
|
||||
"full_name" : "user with mixed privileges to multiple indices"
|
||||
}
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_read
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_index
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_delete
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: everything
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
---
|
||||
teardown:
|
||||
- do:
|
||||
xpack.security.delete_user:
|
||||
username: "test_user"
|
||||
ignore: 404
|
||||
|
||||
- do:
|
||||
xpack.security.delete_role:
|
||||
name: "mixed_role"
|
||||
ignore: 404
|
||||
|
||||
---
|
||||
"Test indexing a document when allowed":
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
create:
|
||||
id: 1
|
||||
index: only_index
|
||||
type: doc
|
||||
body: >
|
||||
{
|
||||
"name" : "doc1"
|
||||
}
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
create:
|
||||
id: 2
|
||||
index: everything
|
||||
type: doc
|
||||
body: >
|
||||
{
|
||||
"name" : "doc2"
|
||||
}
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "only_index", "_type": "doc", "_id": "3"}}'
|
||||
- '{"name": "doc3"}'
|
||||
- '{"index": {"_index": "everything", "_type": "doc", "_id": "4"}}'
|
||||
- '{"name": "doc4"}'
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "only_index", "_type": "doc", "_id": "5"}}'
|
||||
- '{"name": "doc5"}'
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "everything", "_type": "doc", "_id": "6"}}'
|
||||
- '{"name": "doc6"}'
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_index
|
||||
|
||||
- match: { hits.total: 3 }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: everything
|
||||
|
||||
- match: { hits.total: 3 }
|
||||
|
||||
---
|
||||
"Test indexing a document when not allowed":
|
||||
- do:
|
||||
catch: forbidden
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
create:
|
||||
refresh: true
|
||||
id: 7
|
||||
index: only_read
|
||||
type: doc
|
||||
body: >
|
||||
{
|
||||
"name" : "doc7"
|
||||
}
|
||||
|
||||
- do:
|
||||
catch: forbidden
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
create:
|
||||
refresh: true
|
||||
id: 8
|
||||
index: only_delete
|
||||
type: doc
|
||||
body: >
|
||||
{
|
||||
"name" : "doc8"
|
||||
}
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "only_read", "_type": "doc", "_id": "9"}}'
|
||||
- '{"name": "doc9"}'
|
||||
- '{"index": {"_index": "only_delete", "_type": "doc", "_id": "10"}}'
|
||||
- '{"name": "doc10"}'
|
||||
- match: { errors: true }
|
||||
- match: { items.0.index.status: 403 }
|
||||
- match: { items.0.index.error.type: "security_exception" }
|
||||
- match: { items.1.index.status: 403 }
|
||||
- match: { items.1.index.error.type: "security_exception" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "only_read", "_type": "doc", "_id": "11"}}'
|
||||
- '{"name": "doc11"}'
|
||||
- match: { errors: true }
|
||||
- match: { items.0.index.status: 403 }
|
||||
- match: { items.0.index.error.type: "security_exception" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "only_delete", "_type": "doc", "_id": "12"}}'
|
||||
- '{"name": "doc12"}'
|
||||
- match: { errors: true }
|
||||
- match: { items.0.index.status: 403 }
|
||||
- match: { items.0.index.error.type: "security_exception" }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_read
|
||||
- match: { hits.total: 0 }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_delete
|
||||
- match: { hits.total: 0 }
|
||||
|
||||
---
|
||||
"Test bulk indexing documents when only some are allowed":
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "only_read", "_type": "doc", "_id": "13"}}'
|
||||
- '{"name": "doc13"}'
|
||||
- '{"index": {"_index": "only_index", "_type": "doc", "_id": "14"}}'
|
||||
- '{"name": "doc14"}'
|
||||
- match: { errors: true }
|
||||
- match: { items.0.index.status: 403 }
|
||||
- match: { items.0.index.error.type: "security_exception" }
|
||||
- match: { items.1.index.status: 201 }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_index
|
||||
body: { "query": { "term": { "_id": "14" } } }
|
||||
- match: { hits.total: 1 }
|
|
@ -0,0 +1,331 @@
|
|||
---
|
||||
setup:
|
||||
- skip:
|
||||
features: headers
|
||||
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
xpack.security.put_role:
|
||||
name: "mixed_role"
|
||||
body: >
|
||||
{
|
||||
"indices": [
|
||||
{ "names": ["only_read"], "privileges": ["read"] },
|
||||
{ "names": ["only_index"], "privileges": ["index"] },
|
||||
{ "names": ["only_delete"], "privileges": ["delete"] },
|
||||
{ "names": ["everything"], "privileges": ["all"] }
|
||||
]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.security.put_user:
|
||||
username: "test_user"
|
||||
body: >
|
||||
{
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : [ "mixed_role" ],
|
||||
"full_name" : "user with mixed privileges to multiple indices"
|
||||
}
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_read
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_index
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_delete
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: everything
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
|
||||
- do:
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "only_read", "_type": "doc", "_id": "1"}}'
|
||||
- '{"name": "doc1"}'
|
||||
- '{"index": {"_index": "only_index", "_type": "doc", "_id": "2"}}'
|
||||
- '{"name": "doc2"}'
|
||||
- '{"index": {"_index": "only_delete", "_type": "doc", "_id": "3"}}'
|
||||
- '{"name": "doc3"}'
|
||||
- '{"index": {"_index": "only_delete", "_type": "doc", "_id": "4"}}'
|
||||
- '{"name": "doc4"}'
|
||||
- '{"index": {"_index": "only_delete", "_type": "doc", "_id": "5"}}'
|
||||
- '{"name": "doc5"}'
|
||||
- '{"index": {"_index": "only_delete", "_type": "doc", "_id": "6"}}'
|
||||
- '{"name": "doc6"}'
|
||||
- '{"index": {"_index": "only_delete", "_type": "doc", "_id": "7"}}'
|
||||
- '{"name": "doc7"}'
|
||||
- '{"index": {"_index": "everything", "_type": "doc", "_id": "8"}}'
|
||||
- '{"name": "doc8"}'
|
||||
- '{"index": {"_index": "everything", "_type": "doc", "_id": "9"}}'
|
||||
- '{"name": "doc9"}'
|
||||
- '{"index": {"_index": "everything", "_type": "doc", "_id": "10"}}'
|
||||
- '{"name": "doc10"}'
|
||||
|
||||
---
|
||||
teardown:
|
||||
- do:
|
||||
xpack.security.delete_user:
|
||||
username: "test_user"
|
||||
ignore: 404
|
||||
|
||||
- do:
|
||||
xpack.security.delete_role:
|
||||
name: "mixed_role"
|
||||
ignore: 404
|
||||
|
||||
---
|
||||
"Test deleting a document when allowed":
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_delete
|
||||
body: { "query": { "terms": { "_id": [ "3", "4", "5" ] } } }
|
||||
- match: { hits.total: 3 }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: everything
|
||||
body: { "query": { "terms": { "_id": [ "8", "9", "10" ] } } }
|
||||
- match: { hits.total: 3 }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
delete:
|
||||
refresh: true
|
||||
index: only_delete
|
||||
type: doc
|
||||
id: 3
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
delete:
|
||||
refresh: true
|
||||
index: everything
|
||||
type: doc
|
||||
id: 8
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"delete": {"_index": "only_delete", "_type": "doc", "_id": "4"}}'
|
||||
- '{"delete": {"_index": "everything" , "_type": "doc", "_id": "9"}}'
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body: # The rest test won't send streaming content unless it has multiple bodies, so we send the same delete twice
|
||||
- '{"delete": {"_index": "only_delete", "_type": "doc", "_id": "5"}}'
|
||||
- '{"delete": {"_index": "only_delete", "_type": "doc", "_id": "5"}}'
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body: # The rest test won't send streaming content unless it has multiple bodies, so we send the same delete twice
|
||||
- delete:
|
||||
_index: everything
|
||||
_type: doc
|
||||
_id: 10
|
||||
- delete:
|
||||
_index: everything
|
||||
_type: doc
|
||||
_id: 10
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_delete
|
||||
body: { "query": { "terms": { "_id": [ "3", "4", "5" ] } } }
|
||||
- match: { hits.total: 0 }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: everything
|
||||
body: { "query": { "terms": { "_id": [ "8", "9", "10" ] } } }
|
||||
- match: { hits.total: 0 }
|
||||
|
||||
---
|
||||
"Test deleting a document when not allowed":
|
||||
- do:
|
||||
catch: forbidden
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
delete:
|
||||
refresh: true
|
||||
index: only_read
|
||||
type: doc
|
||||
id: 1
|
||||
|
||||
- do:
|
||||
catch: forbidden
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
delete:
|
||||
refresh: true
|
||||
index: only_index
|
||||
type: doc
|
||||
id: 2
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"delete": {"_index": "only_read" , "_type": "doc", "_id": "1"}}'
|
||||
- '{"delete": {"_index": "only_index", "_type": "doc", "_id": "2"}}'
|
||||
|
||||
- match: { errors: true }
|
||||
- match: { items.0.delete.status: 403 }
|
||||
- match: { items.0.delete.error.type: "security_exception" }
|
||||
- match: { items.1.delete.status: 403 }
|
||||
- match: { items.1.delete.error.type: "security_exception" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body: # The rest test won't send streaming content unless it has multiple bodies, so we send the same delete twice
|
||||
- '{"delete": {"_index": "only_read" , "_type": "doc", "_id": "1"}}'
|
||||
- '{"delete": {"_index": "only_read" , "_type": "doc", "_id": "1"}}'
|
||||
|
||||
- match: { errors: true }
|
||||
- match: { items.0.delete.status: 403 }
|
||||
- match: { items.0.delete.error.type: "security_exception" }
|
||||
- match: { items.1.delete.status: 403 }
|
||||
- match: { items.1.delete.error.type: "security_exception" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body: # The rest test won't send streaming content unless it has multiple bodies, so we send the same delete twice
|
||||
- '{"delete": {"_index": "only_index", "_type": "doc", "_id": "2"}}'
|
||||
- '{"delete": {"_index": "only_index", "_type": "doc", "_id": "2"}}'
|
||||
|
||||
- match: { errors: true }
|
||||
- match: { items.0.delete.status: 403 }
|
||||
- match: { items.0.delete.error.type: "security_exception" }
|
||||
- match: { items.1.delete.status: 403 }
|
||||
- match: { items.1.delete.error.type: "security_exception" }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_read
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_index
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
|
||||
---
|
||||
"Test bulk delete documents when only some are allowed":
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"delete": {"_index": "only_read" , "_type": "doc", "_id": "1"}}'
|
||||
- '{"delete": {"_index": "only_delete", "_type": "doc", "_id": "6"}}'
|
||||
- match: { errors: true }
|
||||
- match: { items.0.delete.status: 403 }
|
||||
- match: { items.0.delete.error.type: "security_exception" }
|
||||
- match: { items.1.delete.status: 200 }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_read
|
||||
body: { "query": { "term": { "_id": "1" } } }
|
||||
- match: { hits.total: 1 }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_delete
|
||||
body: { "query": { "term": { "_id": "6" } } }
|
||||
- match: { hits.total: 0 }
|
||||
|
||||
---
|
||||
"Test bulk delete and index documents when only some are allowed":
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index" : {"_index": "only_delete", "_type": "doc", "_id": "11"}}'
|
||||
- '{"name" : "doc11"}'
|
||||
- '{"delete": {"_index": "only_delete", "_type": "doc", "_id": "7"}}'
|
||||
- '{"index" : {"_index": "only_index", "_type": "doc", "_id": "12"}}'
|
||||
- '{"name" : "doc12"}'
|
||||
- '{"delete": {"_index": "only_index", "_type": "doc", "_id": "2"}}'
|
||||
- match: { errors: true }
|
||||
- match: { items.0.index.status: 403 }
|
||||
- match: { items.0.index.error.type: "security_exception" }
|
||||
- match: { items.1.delete.status: 200 }
|
||||
- match: { items.2.index.status: 201 }
|
||||
- match: { items.3.delete.status: 403 }
|
||||
- match: { items.3.delete.error.type: "security_exception" }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_delete
|
||||
body: { "query": { "terms": { "_id": [ "11", "7" ] } } }
|
||||
# 11 wasn't created, 7 was deleted
|
||||
- match: { hits.total: 0 }
|
||||
|
||||
- do: # superuser
|
||||
search:
|
||||
index: only_index
|
||||
body: { "query": { "terms": { "_id": [ "12", "2" ] } } }
|
||||
# 12 was created, 2 wasn't deleted
|
||||
- match: { hits.total: 2 }
|
|
@ -0,0 +1,291 @@
|
|||
---
|
||||
setup:
|
||||
- skip:
|
||||
features: headers
|
||||
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
xpack.security.put_role:
|
||||
name: "mixed_role"
|
||||
body: >
|
||||
{
|
||||
"indices": [
|
||||
{ "names": ["only_read"], "privileges": ["read"] },
|
||||
{ "names": ["only_index"], "privileges": ["index"] },
|
||||
{ "names": ["only_delete"], "privileges": ["delete"] },
|
||||
{ "names": ["read_write"], "privileges": ["read", "write"] },
|
||||
{ "names": ["everything"], "privileges": ["all"] }
|
||||
]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.security.put_user:
|
||||
username: "test_user"
|
||||
body: >
|
||||
{
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : [ "mixed_role" ],
|
||||
"full_name" : "user with mixed privileges to multiple indices"
|
||||
}
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_read
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_index
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_delete
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
- do:
|
||||
indices.create:
|
||||
index: read_write
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
- do:
|
||||
indices.create:
|
||||
index: everything
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
|
||||
- do:
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "only_read", "_type": "doc", "_id": "1"}}'
|
||||
- '{"name": "doc1"}'
|
||||
- '{"index": {"_index": "only_index", "_type": "doc", "_id": "2"}}'
|
||||
- '{"name": "doc2"}'
|
||||
- '{"index": {"_index": "only_delete", "_type": "doc", "_id": "3"}}'
|
||||
- '{"name": "doc3"}'
|
||||
- '{"index": {"_index": "read_write", "_type": "doc", "_id": "4"}}'
|
||||
- '{"name": "doc4"}'
|
||||
- '{"index": {"_index": "everything", "_type": "doc", "_id": "5"}}'
|
||||
- '{"name": "doc5"}'
|
||||
|
||||
---
|
||||
teardown:
|
||||
- do:
|
||||
xpack.security.delete_user:
|
||||
username: "test_user"
|
||||
ignore: 404
|
||||
|
||||
- do:
|
||||
xpack.security.delete_role:
|
||||
name: "mixed_role"
|
||||
ignore: 404
|
||||
|
||||
---
|
||||
"Test get a document when authorized":
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
get:
|
||||
id: 1
|
||||
index: only_read
|
||||
type: doc
|
||||
|
||||
- match: { _index: only_read }
|
||||
- match: { _id: "1" }
|
||||
- match: { _source.name: "doc1" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
get:
|
||||
id: 4
|
||||
index: read_write
|
||||
type: doc
|
||||
- match: { _index: read_write }
|
||||
- match: { _id: "4" }
|
||||
- match: { _source.name: "doc4" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
get:
|
||||
id: 5
|
||||
index: everything
|
||||
type: doc
|
||||
- match: { _index: everything }
|
||||
- match: { _id: "5" }
|
||||
- match: { _source.name: "doc5" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
mget:
|
||||
body:
|
||||
docs:
|
||||
- { _index: "only_read", _type: "doc", _id: "1" }
|
||||
- { _index: "read_write", _type: "doc", _id: "4" }
|
||||
- { _index: "everything", _type: "doc", _id: "5" }
|
||||
- match: { docs.0._index: "only_read" }
|
||||
- match: { docs.0._id: "1" }
|
||||
- match: { docs.0._source.name: "doc1" }
|
||||
- match: { docs.1._index: "read_write" }
|
||||
- match: { docs.1._id: "4" }
|
||||
- match: { docs.1._source.name: "doc4" }
|
||||
- match: { docs.2._index: "everything"}
|
||||
- match: { docs.2._id: "5" }
|
||||
- match: { docs.2._source.name: "doc5" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
mget:
|
||||
body:
|
||||
docs:
|
||||
- { _index: "only_read", _type: "doc", _id: "1" }
|
||||
- match: { docs.0._index: "only_read"}
|
||||
- match: { docs.0._id: "1" }
|
||||
- match: { docs.0._source.name: "doc1" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
mget:
|
||||
body:
|
||||
docs:
|
||||
- { _index: "read_write", _type: "doc", _id: "4" }
|
||||
- match: { docs.0._index: read_write}
|
||||
- match: { docs.0._id: "4" }
|
||||
- match: { docs.0._source.name: "doc4" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
mget:
|
||||
body:
|
||||
docs:
|
||||
- { _index: "everything", _type: "doc", _id: "5" }
|
||||
- match: { docs.0._index: "everything"}
|
||||
- match: { docs.0._id: "5" }
|
||||
- match: { docs.0._source.name: "doc5" }
|
||||
|
||||
---
|
||||
"Test get a document when not allowed":
|
||||
|
||||
- do:
|
||||
catch: forbidden
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
get:
|
||||
id: 2
|
||||
index: only_index
|
||||
type: doc
|
||||
|
||||
- do:
|
||||
catch: forbidden
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
get:
|
||||
id: 3
|
||||
index: only_delete
|
||||
type: doc
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
mget:
|
||||
body:
|
||||
docs:
|
||||
- { _index: "only_index", _type: "doc", _id: "2" }
|
||||
- { _index: "only_delete", _type: "doc", _id: "3" }
|
||||
- match: { docs.0._index: "only_index"}
|
||||
- match: { docs.0._id: "2" }
|
||||
- match: { docs.0.error.type: "security_exception" }
|
||||
- match: { docs.1._index: "only_delete"}
|
||||
- match: { docs.1._id: "3" }
|
||||
- match: { docs.1.error.type: "security_exception" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
mget:
|
||||
body:
|
||||
docs:
|
||||
- { _index: "only_index", _type: "doc", _id: "2" }
|
||||
- match: { docs.0._index: "only_index"}
|
||||
- match: { docs.0._id: "2" }
|
||||
- match: { docs.0.error.type: "security_exception" }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
mget:
|
||||
body:
|
||||
docs:
|
||||
- { _index: "only_delete", _type: "doc", _id: "3" }
|
||||
- match: { docs.0._index: "only_delete"}
|
||||
- match: { docs.0._id: "3" }
|
||||
- match: { docs.0.error.type: "security_exception" }
|
||||
|
||||
---
|
||||
"Test mget documents when only some are allowed":
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
mget:
|
||||
body:
|
||||
docs:
|
||||
- { _index: "only_read" , _type: "doc", _id: "1" }
|
||||
- { _index: "only_index" , _type: "doc", _id: "2" }
|
||||
- { _index: "only_delete", _type: "doc", _id: "3" }
|
||||
- { _index: "read_write" , _type: "doc", _id: "4" }
|
||||
- { _index: "everything" , _type: "doc", _id: "5" }
|
||||
|
||||
- match: { docs.0._index: "only_read" }
|
||||
- match: { docs.0._id: "1" }
|
||||
- match: { docs.0._source.name: "doc1" }
|
||||
- match: { docs.1._index: "only_index"}
|
||||
- match: { docs.1._id: "2" }
|
||||
- match: { docs.1.error.type: "security_exception" }
|
||||
- match: { docs.2._index: "only_delete"}
|
||||
- match: { docs.2._id: "3" }
|
||||
- match: { docs.2.error.type: "security_exception" }
|
||||
- match: { docs.3._index: "read_write" }
|
||||
- match: { docs.3._id: "4" }
|
||||
- match: { docs.3._source.name: "doc4" }
|
||||
- match: { docs.4._index: "everything" }
|
||||
- match: { docs.4._id: "5" }
|
||||
- match: { docs.4._source.name: "doc5" }
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
---
|
||||
setup:
|
||||
- skip:
|
||||
features: headers
|
||||
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
xpack.security.put_role:
|
||||
name: "mixed_role"
|
||||
body: >
|
||||
{
|
||||
"indices": [
|
||||
{ "names": ["only_read"], "privileges": ["read"] },
|
||||
{ "names": ["only_index"], "privileges": ["index"] },
|
||||
{ "names": ["only_delete"], "privileges": ["delete"] },
|
||||
{ "names": ["read_write"], "privileges": ["read", "write"] },
|
||||
{ "names": ["everything"], "privileges": ["all"] }
|
||||
]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.security.put_user:
|
||||
username: "test_user"
|
||||
body: >
|
||||
{
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : [ "mixed_role" ],
|
||||
"full_name" : "user with mixed privileges to multiple indices"
|
||||
}
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_read
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
tag:
|
||||
type: "keyword"
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_index
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
tag:
|
||||
type: "keyword"
|
||||
- do:
|
||||
indices.create:
|
||||
index: only_delete
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
tag:
|
||||
type: "keyword"
|
||||
- do:
|
||||
indices.create:
|
||||
index: read_write
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
tag:
|
||||
type: "keyword"
|
||||
- do:
|
||||
indices.create:
|
||||
index: everything
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
doc:
|
||||
properties:
|
||||
name:
|
||||
type: "keyword"
|
||||
tag:
|
||||
type: "keyword"
|
||||
- do:
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "only_read", "_type": "doc", "_id": "1"}}'
|
||||
- '{"name": "doc1", "tag": [ "can-read", "tag-a" ] }'
|
||||
- '{"index": {"_index": "only_read", "_type": "doc", "_id": "2"}}'
|
||||
- '{"name": "doc2", "tag": [ "can-read", "tag-b"] }'
|
||||
- '{"index": {"_index": "only_index", "_type": "doc", "_id": "3"}}'
|
||||
- '{"name": "doc3", "tag": [ "no-read", "tag-a"] }'
|
||||
- '{"index": {"_index": "only_index", "_type": "doc", "_id": "4"}}'
|
||||
- '{"name": "doc4", "tag": [ "no-read", "tag-b"] }'
|
||||
- '{"index": {"_index": "only_delete", "_type": "doc", "_id": "5"}}'
|
||||
- '{"name": "doc5", "tag": [ "no-read", "tag-a"] }'
|
||||
- '{"index": {"_index": "only_delete", "_type": "doc", "_id": "6"}}'
|
||||
- '{"name": "doc6", "tag": [ "no-read", "tag-b"] }'
|
||||
- '{"index": {"_index": "read_write", "_type": "doc", "_id": "7"}}'
|
||||
- '{"name": "doc7", "tag": [ "can-read", "tag-a" ] }'
|
||||
- '{"index": {"_index": "read_write", "_type": "doc", "_id": "8"}}'
|
||||
- '{"name": "doc8", "tag": [ "can-read", "tag-b"] }'
|
||||
- '{"index": {"_index": "everything", "_type": "doc", "_id": "9"}}'
|
||||
- '{"name": "doc9", "tag": [ "can-read", "tag-a" ] }'
|
||||
- '{"index": {"_index": "everything", "_type": "doc", "_id": "10"}}'
|
||||
- '{"name": "doc10", "tag": [ "can-read", "tag-b"] }'
|
||||
|
||||
---
|
||||
teardown:
|
||||
- do:
|
||||
xpack.security.delete_user:
|
||||
username: "test_user"
|
||||
ignore: 404
|
||||
|
||||
- do:
|
||||
xpack.security.delete_role:
|
||||
name: "mixed_role"
|
||||
ignore: 404
|
||||
|
||||
---
|
||||
"Test search for document when authorized":
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
search:
|
||||
index: only_read
|
||||
body:
|
||||
- match: { hits.total: 2 }
|
||||
- match: { hits.hits.0._index: only_read }
|
||||
- match: { hits.hits.1._index: only_read }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
search:
|
||||
index: read_write
|
||||
body:
|
||||
- match: { hits.total: 2 }
|
||||
- match: { hits.hits.0._index: read_write }
|
||||
- match: { hits.hits.1._index: read_write }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
search:
|
||||
index: everything
|
||||
body:
|
||||
- match: { hits.total: 2 }
|
||||
- match: { hits.hits.0._index: everything }
|
||||
- match: { hits.hits.1._index: everything }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
search:
|
||||
body: { "query": { "term": { "tag": "can-read" } } }
|
||||
- match: { hits.total: 6 }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
msearch:
|
||||
body:
|
||||
- { }
|
||||
- { "query": { "term": { "tag": "can-read" } } }
|
||||
- { "index": "only_read" }
|
||||
- { "query": { "term": { "tag": "tag-a" } } }
|
||||
- { "index": "read_write" }
|
||||
- { }
|
||||
- match: { responses.0.hits.total: 6 }
|
||||
- match: { responses.1.hits.total: 1 }
|
||||
- match: { responses.2.hits.total: 2 }
|
||||
|
||||
---
|
||||
"Test search for documents when not allowed":
|
||||
|
||||
- do:
|
||||
catch: forbidden
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
search:
|
||||
index: only_index
|
||||
body:
|
||||
|
||||
- do:
|
||||
catch: forbidden
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
search:
|
||||
index: only_delete
|
||||
body:
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
search:
|
||||
body: { "query": { "term": { "tag": "no-read" } } }
|
||||
- match: { hits.total: 0 }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
search:
|
||||
body: { "query": { "term": { "_index": "only_index" } } }
|
||||
- match: { hits.total: 0 }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
msearch:
|
||||
body:
|
||||
- { }
|
||||
- { "query": { "term": { "tag": "no-read" } } }
|
||||
- { }
|
||||
- { "query": { "term": { "_index": "only_index" } } }
|
||||
- { "index": "only_delete" }
|
||||
- { }
|
||||
- match: { responses.0.hits.total: 0 }
|
||||
- match: { responses.1.hits.total: 0 }
|
||||
- match: { responses.2.error.type: "security_exception" }
|
||||
|
||||
---
|
||||
"Test search documents when only some are allowed":
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
search:
|
||||
body: { "query": { "term": { "tag": "tag-a" } } }
|
||||
- match: { hits.total: 3 } # can-read, read_write, everything
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
|
||||
msearch:
|
||||
body:
|
||||
- { }
|
||||
- { "query": { "term": { "tag": "tag-a" } } }
|
||||
- { }
|
||||
- { "query": { "term": { "tag": "can-read" } } }
|
||||
- { }
|
||||
- { "query": { "term": { "tag": "no-read" } } }
|
||||
- { "index": "only_read" }
|
||||
- { "query": { "term": { "tag": "tag-a" } } }
|
||||
- { "index": "only_delete" }
|
||||
- { "query": { "term": { "tag": "tag-a" } } }
|
||||
- match: { responses.0.hits.total: 3 } # tag-a (in readable indices)
|
||||
- match: { responses.1.hits.total: 6 } # can-read
|
||||
- match: { responses.2.hits.total: 0 } # no-read
|
||||
- match: { responses.3.hits.total: 1 } # only_read + tag-a
|
||||
- match: { responses.4.error.type: "security_exception" } # only_delete + tag-a
|
|
@ -15,3 +15,4 @@ minimal:
|
|||
- indices:data/read/search
|
||||
- indices:data/write/bulk
|
||||
- indices:data/write/index
|
||||
- indices:data/write/delete
|
||||
|
|
Loading…
Reference in New Issue