security: protect the user and roles index
This commit adds the logic to protect the user and roles index that we store locally by restricting access to the internal XPack user. We need to do this in two places; the first is when resolving wildcards and the other is when authorizing requests made against specific indices. Original commit: elastic/x-pack-elasticsearch@8ee0ce02db
This commit is contained in:
parent
c1c78911b9
commit
186dbf547a
|
@ -48,7 +48,8 @@ public class TransportClearRealmCacheAction extends TransportNodesAction<ClearRe
|
|||
Object resp = responses.get(i);
|
||||
if (resp instanceof ClearRealmCacheResponse.Node) {
|
||||
nodes.add((ClearRealmCacheResponse.Node) resp);
|
||||
} else {
|
||||
} else if (resp != null) {
|
||||
// null is possible if there is an error and we do not accumulate exceptions...
|
||||
throw new IllegalArgumentException("node response [" + resp.getClass() + "] is not the correct type");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,8 @@ public class TransportClearRolesCacheAction extends TransportNodesAction<ClearRo
|
|||
Object resp = nodesResponses.get(i);
|
||||
if (resp instanceof ClearRolesCacheResponse.Node) {
|
||||
responses.add((ClearRolesCacheResponse.Node) resp);
|
||||
} else {
|
||||
} else if (resp == null) {
|
||||
// null is possible if there is an error and we do not accumulate exceptions...
|
||||
throw new IllegalArgumentException("node response [" + resp.getClass() + "] is not the correct type");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.search.action.SearchTransportService;
|
||||
import org.elasticsearch.shield.ShieldTemplateService;
|
||||
import org.elasticsearch.shield.SystemUser;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.XPackUser;
|
||||
|
@ -112,6 +113,13 @@ public class InternalAuthorizationService extends AbstractComponent implements A
|
|||
}
|
||||
}
|
||||
|
||||
if (XPackUser.is(user) == false) {
|
||||
// we should filter out the .security index from wildcards
|
||||
if (indicesAndAliases.remove(ShieldTemplateService.SECURITY_INDEX_NAME)) {
|
||||
logger.debug("removed [{}] from user [{}] list of authorized indices",
|
||||
ShieldTemplateService.SECURITY_INDEX_NAME, user.principal());
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(indicesAndAliases);
|
||||
}
|
||||
|
||||
|
@ -208,6 +216,13 @@ public class InternalAuthorizationService extends AbstractComponent implements A
|
|||
IndicesAccessControl indicesAccessControl = permission.authorize(action, indexNames, metaData);
|
||||
if (!indicesAccessControl.isGranted()) {
|
||||
throw denial(user, action, request);
|
||||
} else if (indicesAccessControl.getIndexPermissions(ShieldTemplateService.SECURITY_INDEX_NAME) != null
|
||||
&& indicesAccessControl.getIndexPermissions(ShieldTemplateService.SECURITY_INDEX_NAME).isGranted()
|
||||
&& XPackUser.is(user) == false) {
|
||||
// only the XPackUser is allowed to work with this index, but we should allow health/stats through
|
||||
logger.debug("user [{}] attempted to directly perform [{}] against the security index [{}]", user.principal(), action,
|
||||
ShieldTemplateService.SECURITY_INDEX_NAME);
|
||||
throw denial(user, action, request);
|
||||
} else {
|
||||
setIndicesAccessControl(indicesAccessControl);
|
||||
}
|
||||
|
|
|
@ -166,6 +166,7 @@ public class DefaultIndicesAndAliasesResolver implements IndicesAndAliasesResolv
|
|||
private List<String> replaceWildcardsWithAuthorizedIndices(String[] indices, IndicesOptions indicesOptions, MetaData metaData,
|
||||
List<String> authorizedIndices) {
|
||||
|
||||
// check for all and return list of authorized indices
|
||||
if (IndexNameExpressionResolver.isAllIndices(indicesList(indices))) {
|
||||
List<String> visibleIndices = new ArrayList<>();
|
||||
for (String authorizedIndex : authorizedIndices) {
|
||||
|
|
|
@ -16,17 +16,15 @@ import org.elasticsearch.rest.RestStatus;
|
|||
import org.elasticsearch.shield.action.role.PutRoleResponse;
|
||||
import org.elasticsearch.shield.action.role.GetRolesResponse;
|
||||
import org.elasticsearch.shield.ShieldTemplateService;
|
||||
import org.elasticsearch.shield.authc.esnative.ESNativeUsersStore;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.shield.authz.RoleDescriptor;
|
||||
import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore;
|
||||
import org.elasticsearch.shield.client.SecurityClient;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
import org.elasticsearch.test.NativeRealmIntegTestCase;
|
||||
import org.elasticsearch.test.ShieldSettingsSource;
|
||||
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||
import org.elasticsearch.test.rest.client.http.HttpResponse;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
|
@ -35,7 +33,6 @@ import java.util.List;
|
|||
|
||||
import static org.hamcrest.Matchers.arrayWithSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.isOneOf;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
/**
|
||||
|
@ -43,7 +40,7 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
* test the cache clearing APIs.
|
||||
*/
|
||||
@TestLogging("shield.authc.esnative:TRACE,shield.authz.esnative:TRACE,integration:DEBUG")
|
||||
public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
||||
public class ClearRolesCacheTests extends NativeRealmIntegTestCase {
|
||||
|
||||
private static String[] roles;
|
||||
|
||||
|
@ -56,29 +53,7 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
@Before
|
||||
public void setupForTest() throws Exception {
|
||||
// Clear the realm cache for all realms since we use a SUITE scoped cluster
|
||||
SecurityClient client = securityClient(internalCluster().transportClient());
|
||||
client.prepareClearRealmCache().get();
|
||||
|
||||
for (ESNativeUsersStore store : internalCluster().getInstances(ESNativeUsersStore.class)) {
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), is(ESNativeUsersStore.State.STARTED));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (ESNativeRolesStore store : internalCluster().getInstances(ESNativeRolesStore.class)) {
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), is(ESNativeRolesStore.State.STARTED));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setupForTests() {
|
||||
SecurityClient c = securityClient();
|
||||
// create roles
|
||||
for (String role : roles) {
|
||||
|
@ -129,13 +104,11 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
public void testModifyingDocumentsDirectly() throws Exception {
|
||||
Client client = internalCluster().transportClient();
|
||||
|
||||
int modifiedRolesCount = randomIntBetween(1, roles.length);
|
||||
List<String> toModify = randomSubsetOf(modifiedRolesCount, roles);
|
||||
logger.debug("--> modifying roles {} to have run_as", toModify);
|
||||
for (String role : toModify) {
|
||||
UpdateResponse response = client.prepareUpdate().setId(role).setIndex(ShieldTemplateService.SECURITY_INDEX_NAME)
|
||||
UpdateResponse response = internalClient().prepareUpdate().setId(role).setIndex(ShieldTemplateService.SECURITY_INDEX_NAME)
|
||||
.setType(ESNativeRolesStore.ROLE_DOC_TYPE)
|
||||
.setDoc("run_as", new String[] { role })
|
||||
.get();
|
||||
|
@ -145,7 +118,7 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
|||
|
||||
// in this test, the poller runs too frequently to check the cache still has roles without run as
|
||||
// clear the cache and we should definitely see the latest values!
|
||||
SecurityClient securityClient = securityClient(client);
|
||||
SecurityClient securityClient = securityClient(internalCluster().transportClient());
|
||||
final boolean useHttp = randomBoolean();
|
||||
final boolean clearAll = randomBoolean();
|
||||
logger.debug("--> starting to clear roles. using http [{}] clearing all [{}]", useHttp, clearAll);
|
||||
|
@ -171,14 +144,13 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
public void testDeletingRoleDocumentDirectly() throws Exception {
|
||||
Client client = internalCluster().transportClient();
|
||||
SecurityClient securityClient = securityClient(client);
|
||||
SecurityClient securityClient = securityClient(internalCluster().transportClient());
|
||||
|
||||
final String role = randomFrom(roles);
|
||||
RoleDescriptor[] foundRoles = securityClient.prepareGetRoles().names(role).get().roles();
|
||||
assertThat(foundRoles.length, is(1));
|
||||
logger.debug("--> deleting role [{}]", role);
|
||||
DeleteResponse response = client
|
||||
DeleteResponse response = internalClient()
|
||||
.prepareDelete(ShieldTemplateService.SECURITY_INDEX_NAME, ESNativeRolesStore.ROLE_DOC_TYPE, role).get();
|
||||
assertThat(response.isFound(), is(true));
|
||||
|
||||
|
@ -205,31 +177,4 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopESNativeStores() throws Exception {
|
||||
for (ESNativeUsersStore store : internalCluster().getInstances(ESNativeUsersStore.class)) {
|
||||
store.stop();
|
||||
// the store may already be stopping so wait until it is stopped
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), isOneOf(ESNativeUsersStore.State.STOPPED, ESNativeUsersStore.State.FAILED));
|
||||
}
|
||||
});
|
||||
store.reset();
|
||||
}
|
||||
|
||||
for (ESNativeRolesStore store : internalCluster().getInstances(ESNativeRolesStore.class)) {
|
||||
store.stop();
|
||||
// the store may already be stopping so wait until it is stopped
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), isOneOf(ESNativeRolesStore.State.STOPPED, ESNativeRolesStore.State.FAILED));
|
||||
}
|
||||
});
|
||||
store.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,13 +20,10 @@ import org.elasticsearch.shield.action.user.DeleteUserResponse;
|
|||
import org.elasticsearch.shield.action.user.GetUsersResponse;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authz.RoleDescriptor;
|
||||
import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore;
|
||||
import org.elasticsearch.shield.authz.permission.Role;
|
||||
import org.elasticsearch.shield.client.SecurityClient;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
import org.elasticsearch.test.NativeRealmIntegTestCase;
|
||||
import org.elasticsearch.test.ShieldSettingsSource;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -36,12 +33,11 @@ import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basic
|
|||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.isOneOf;
|
||||
|
||||
/**
|
||||
* Tests for the ESNativeUsersStore and ESNativeRolesStore
|
||||
*/
|
||||
public class ESNativeTests extends ShieldIntegTestCase {
|
||||
public class ESNativeTests extends NativeRealmIntegTestCase {
|
||||
|
||||
public void testDeletingNonexistingUserAndRole() throws Exception {
|
||||
SecurityClient c = securityClient();
|
||||
|
@ -390,56 +386,4 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
.admin().cluster().prepareHealth().get();
|
||||
assertFalse(response.isTimedOut());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void ensureStoresStarted() throws Exception {
|
||||
// Clear the realm cache for all realms since we use a SUITE scoped cluster
|
||||
SecurityClient client = securityClient();
|
||||
client.prepareClearRealmCache().get();
|
||||
|
||||
for (ESNativeUsersStore store : internalCluster().getInstances(ESNativeUsersStore.class)) {
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), is(ESNativeUsersStore.State.STARTED));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (ESNativeRolesStore store : internalCluster().getInstances(ESNativeRolesStore.class)) {
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), is(ESNativeRolesStore.State.STARTED));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopESNativeStores() throws Exception {
|
||||
for (ESNativeUsersStore store : internalCluster().getInstances(ESNativeUsersStore.class)) {
|
||||
store.stop();
|
||||
// the store may already be stopping so wait until it is stopped
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), isOneOf(ESNativeUsersStore.State.STOPPED, ESNativeUsersStore.State.FAILED));
|
||||
}
|
||||
});
|
||||
store.reset();
|
||||
}
|
||||
|
||||
for (ESNativeRolesStore store : internalCluster().getInstances(ESNativeRolesStore.class)) {
|
||||
store.stop();
|
||||
// the store may already be stopping so wait until it is stopped
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), isOneOf(ESNativeRolesStore.State.STOPPED, ESNativeRolesStore.State.FAILED));
|
||||
}
|
||||
});
|
||||
store.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,26 +7,43 @@ package org.elasticsearch.shield.authz;
|
|||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthAction;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
|
||||
import org.elasticsearch.action.admin.indices.alias.Alias;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesAction;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexAction;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
|
||||
import org.elasticsearch.action.delete.DeleteAction;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
import org.elasticsearch.action.get.GetAction;
|
||||
import org.elasticsearch.action.get.GetRequest;
|
||||
import org.elasticsearch.action.index.IndexAction;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.search.ClearScrollAction;
|
||||
import org.elasticsearch.action.search.ClearScrollRequest;
|
||||
import org.elasticsearch.action.search.SearchAction;
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.action.search.SearchScrollAction;
|
||||
import org.elasticsearch.action.search.SearchScrollRequest;
|
||||
import org.elasticsearch.action.termvectors.TermVectorsAction;
|
||||
import org.elasticsearch.action.termvectors.TermVectorsRequest;
|
||||
import org.elasticsearch.action.update.UpdateAction;
|
||||
import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.search.action.SearchTransportService;
|
||||
import org.elasticsearch.shield.ShieldTemplateService;
|
||||
import org.elasticsearch.shield.SystemUser;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.XPackUser;
|
||||
import org.elasticsearch.shield.audit.AuditTrail;
|
||||
import org.elasticsearch.shield.authc.AnonymousService;
|
||||
import org.elasticsearch.shield.authc.DefaultAuthenticationFailureHandler;
|
||||
|
@ -40,6 +57,7 @@ import org.elasticsearch.threadpool.ThreadPool;
|
|||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.test.ShieldTestsUtils.assertAuthenticationException;
|
||||
|
@ -452,4 +470,84 @@ public class InternalAuthorizationServiceTests extends ESTestCase {
|
|||
verify(auditTrail).accessGranted(user, "indices:a", request);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testNonXPackUserCannotExecuteOperationAgainstShieldIndex() {
|
||||
User user = new User("all_access_user", "all_access");
|
||||
when(rolesStore.role("all_access")).thenReturn(Role.builder("all_access")
|
||||
.add(IndexPrivilege.ALL, "*")
|
||||
.cluster(ClusterPrivilege.ALL)
|
||||
.build());
|
||||
ClusterState state = mock(ClusterState.class);
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
when(state.metaData()).thenReturn(MetaData.builder()
|
||||
.put(new IndexMetaData.Builder(ShieldTemplateService.SECURITY_INDEX_NAME)
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||
.numberOfShards(1).numberOfReplicas(0).build(), true)
|
||||
.build());
|
||||
|
||||
List<Tuple<String, TransportRequest>> requests = new ArrayList<>();
|
||||
requests.add(new Tuple<>(DeleteAction.NAME, new DeleteRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(UpdateAction.NAME, new UpdateRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(IndexAction.NAME, new IndexRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(ShieldTemplateService.SECURITY_INDEX_NAME)));
|
||||
requests.add(new Tuple<>(TermVectorsAction.NAME, new TermVectorsRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(GetAction.NAME, new GetRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(TermVectorsAction.NAME, new TermVectorsRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(IndicesAliasesAction.NAME, new IndicesAliasesRequest().addAlias("shield_alias",
|
||||
ShieldTemplateService.SECURITY_INDEX_NAME)));
|
||||
|
||||
for (Tuple<String, TransportRequest> requestTuple : requests) {
|
||||
String action = requestTuple.v1();
|
||||
TransportRequest request = requestTuple.v2();
|
||||
try {
|
||||
internalAuthorizationService.authorize(user, action, request);
|
||||
fail("only the xpack user can execute operation [" + action + "] against the internal index");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [" + action + "] is unauthorized for user [all_access_user]"));
|
||||
verify(auditTrail).accessDenied(user, action, request);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
}
|
||||
|
||||
// we should allow waiting for the health of the index or any index if the user has this permission
|
||||
ClusterHealthRequest request = new ClusterHealthRequest(ShieldTemplateService.SECURITY_INDEX_NAME);
|
||||
internalAuthorizationService.authorize(user, ClusterHealthAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request);
|
||||
|
||||
// multiple indices
|
||||
request = new ClusterHealthRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "foo", "bar");
|
||||
internalAuthorizationService.authorize(user, ClusterHealthAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request);
|
||||
}
|
||||
|
||||
public void testXPackUserCanExecuteOperationAgainstShieldIndex() {
|
||||
ClusterState state = mock(ClusterState.class);
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
when(state.metaData()).thenReturn(MetaData.builder()
|
||||
.put(new IndexMetaData.Builder(ShieldTemplateService.SECURITY_INDEX_NAME)
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||
.numberOfShards(1).numberOfReplicas(0).build(), true)
|
||||
.build());
|
||||
|
||||
List<Tuple<String, TransportRequest>> requests = new ArrayList<>();
|
||||
requests.add(new Tuple<>(DeleteAction.NAME, new DeleteRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(UpdateAction.NAME, new UpdateRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(IndexAction.NAME, new IndexRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(ShieldTemplateService.SECURITY_INDEX_NAME)));
|
||||
requests.add(new Tuple<>(TermVectorsAction.NAME, new TermVectorsRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(GetAction.NAME, new GetRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(TermVectorsAction.NAME, new TermVectorsRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "type", "id")));
|
||||
requests.add(new Tuple<>(IndicesAliasesAction.NAME, new IndicesAliasesRequest().addAlias("shield_alias",
|
||||
ShieldTemplateService.SECURITY_INDEX_NAME)));
|
||||
requests.add(new Tuple<>(ClusterHealthAction.NAME, new ClusterHealthRequest(ShieldTemplateService.SECURITY_INDEX_NAME)));
|
||||
requests.add(new Tuple<>(ClusterHealthAction.NAME,
|
||||
new ClusterHealthRequest(ShieldTemplateService.SECURITY_INDEX_NAME, "foo", "bar")));
|
||||
|
||||
for (Tuple<String, TransportRequest> requestTuple : requests) {
|
||||
String action = requestTuple.v1();
|
||||
TransportRequest request = requestTuple.v2();
|
||||
internalAuthorizationService.authorize(XPackUser.INSTANCE, action, request);
|
||||
verify(auditTrail).accessGranted(XPackUser.INSTANCE, action, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
package org.elasticsearch.shield.authz.indicesresolver;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthAction;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesAction;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesAction;
|
||||
|
@ -20,31 +22,45 @@ import org.elasticsearch.action.search.SearchAction;
|
|||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.client.Requests;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.AliasAction;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.IndexNotFoundException;
|
||||
import org.elasticsearch.shield.ShieldTemplateService;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.authz.AuthorizationService;
|
||||
import org.elasticsearch.shield.XPackUser;
|
||||
import org.elasticsearch.shield.audit.AuditTrail;
|
||||
import org.elasticsearch.shield.authc.AnonymousService;
|
||||
import org.elasticsearch.shield.authc.DefaultAuthenticationFailureHandler;
|
||||
import org.elasticsearch.shield.authz.InternalAuthorizationService;
|
||||
import org.elasticsearch.shield.authz.permission.Role;
|
||||
import org.elasticsearch.shield.authz.privilege.ClusterPrivilege;
|
||||
import org.elasticsearch.shield.authz.privilege.IndexPrivilege;
|
||||
import org.elasticsearch.shield.authz.store.RolesStore;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.hasItems;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class DefaultIndicesResolverTests extends ESTestCase {
|
||||
|
||||
private User user;
|
||||
private User userNoIndices;
|
||||
private RolesStore rolesStore;
|
||||
private MetaData metaData;
|
||||
private DefaultIndicesAndAliasesResolver defaultIndicesResolver;
|
||||
|
||||
|
@ -66,35 +82,23 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
.put(indexBuilder("foofoo").putAlias(AliasMetaData.builder("barbaz")).settings(settings))
|
||||
.put(indexBuilder("bar").settings(settings))
|
||||
.put(indexBuilder("bar-closed").state(IndexMetaData.State.CLOSE).settings(settings))
|
||||
.put(indexBuilder("bar2").settings(settings));
|
||||
.put(indexBuilder("bar2").settings(settings))
|
||||
.put(indexBuilder(ShieldTemplateService.SECURITY_INDEX_NAME).settings(settings));
|
||||
metaData = mdBuilder.build();
|
||||
|
||||
AuthorizationService authzService = mock(AuthorizationService.class);
|
||||
user = new User("user", "role");
|
||||
|
||||
String[] authorizedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "missing", "foofoo-closed"};
|
||||
when(authzService.authorizedIndicesAndAliases(user, SearchAction.NAME))
|
||||
.thenReturn(Collections.unmodifiableList(Arrays.asList(authorizedIndices)));
|
||||
when(authzService.authorizedIndicesAndAliases(user, MultiSearchAction.NAME))
|
||||
.thenReturn(Collections.unmodifiableList(Arrays.asList(authorizedIndices)));
|
||||
when(authzService.authorizedIndicesAndAliases(user, MultiGetAction.NAME))
|
||||
.thenReturn(Collections.unmodifiableList(Arrays.asList(authorizedIndices)));
|
||||
when(authzService.authorizedIndicesAndAliases(user, IndicesAliasesAction.NAME))
|
||||
.thenReturn(Collections.unmodifiableList(Arrays.asList(authorizedIndices)));
|
||||
when(authzService.authorizedIndicesAndAliases(user, GetAliasesAction.NAME))
|
||||
.thenReturn(Collections.unmodifiableList(Arrays.asList(authorizedIndices)));
|
||||
when(authzService.authorizedIndicesAndAliases(user, DeleteIndexAction.NAME))
|
||||
.thenReturn(Collections.unmodifiableList(Arrays.asList(authorizedIndices)));
|
||||
userNoIndices = new User("test", "test");
|
||||
when(authzService.authorizedIndicesAndAliases(userNoIndices, IndicesAliasesAction.NAME))
|
||||
.thenReturn(Collections.<String>emptyList());
|
||||
when(authzService.authorizedIndicesAndAliases(userNoIndices, GetAliasesAction.NAME))
|
||||
.thenReturn(Collections.<String>emptyList());
|
||||
when(authzService.authorizedIndicesAndAliases(userNoIndices, SearchAction.NAME))
|
||||
.thenReturn(Collections.<String>emptyList());
|
||||
when(authzService.authorizedIndicesAndAliases(userNoIndices, MultiSearchAction.NAME))
|
||||
.thenReturn(Collections.<String>emptyList());
|
||||
rolesStore = mock(RolesStore.class);
|
||||
String[] authorizedIndices = new String[] { "bar", "bar-closed", "foofoobar", "foofoo", "missing", "foofoo-closed" };
|
||||
when(rolesStore.role("role")).thenReturn(Role.builder("role").add(IndexPrivilege.ALL, authorizedIndices).build());
|
||||
when(rolesStore.role("test")).thenReturn(Role.builder("test").cluster(ClusterPrivilege.MONITOR).build());
|
||||
ClusterService clusterService = mock(ClusterService.class);
|
||||
ClusterState state = mock(ClusterState.class);
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
when(state.metaData()).thenReturn(metaData);
|
||||
|
||||
InternalAuthorizationService authzService = new InternalAuthorizationService(settings, rolesStore, clusterService,
|
||||
mock(AuditTrail.class), new AnonymousService(settings), new DefaultAuthenticationFailureHandler(), mock(ThreadPool.class));
|
||||
defaultIndicesResolver = new DefaultIndicesAndAliasesResolver(authzService);
|
||||
}
|
||||
|
||||
|
@ -104,8 +108,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
|
||||
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
|
||||
assertThat(indices.size(), equalTo(replacedIndices.length));
|
||||
assertThat(request.indices().length, equalTo(replacedIndices.length));
|
||||
assertThat(indices, hasItems(replacedIndices));
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
}
|
||||
|
||||
public void testResolveEmptyIndicesExpandWilcardsOpen() {
|
||||
|
@ -114,8 +119,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
|
||||
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
|
||||
assertThat(indices.size(), equalTo(replacedIndices.length));
|
||||
assertThat(request.indices().length, equalTo(replacedIndices.length));
|
||||
assertThat(indices, hasItems(replacedIndices));
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
}
|
||||
|
||||
public void testResolveAllExpandWilcardsOpenAndClosed() {
|
||||
|
@ -124,8 +130,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
|
||||
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
|
||||
assertThat(indices.size(), equalTo(replacedIndices.length));
|
||||
assertThat(request.indices().length, equalTo(replacedIndices.length));
|
||||
assertThat(indices, hasItems(replacedIndices));
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
}
|
||||
|
||||
public void testResolveAllExpandWilcardsOpen() {
|
||||
|
@ -134,8 +141,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
|
||||
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
|
||||
assertThat(indices.size(), equalTo(replacedIndices.length));
|
||||
assertThat(request.indices().length, equalTo(replacedIndices.length));
|
||||
assertThat(indices, hasItems(replacedIndices));
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
}
|
||||
|
||||
public void testResolveWildcardsExpandWilcardsOpenAndClosed() {
|
||||
|
@ -144,8 +152,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
|
||||
String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo", "foofoo-closed"};
|
||||
assertThat(indices.size(), equalTo(replacedIndices.length));
|
||||
assertThat(request.indices().length, equalTo(replacedIndices.length));
|
||||
assertThat(indices, hasItems(replacedIndices));
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
}
|
||||
|
||||
public void testResolveWildcardsExpandWilcardsOpen() {
|
||||
|
@ -154,8 +163,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
|
||||
String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo"};
|
||||
assertThat(indices.size(), equalTo(replacedIndices.length));
|
||||
assertThat(request.indices().length, equalTo(replacedIndices.length));
|
||||
assertThat(indices, hasItems(replacedIndices));
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
}
|
||||
|
||||
public void testResolveWildcardsMinusExpandWilcardsOpen() {
|
||||
|
@ -164,8 +174,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
|
||||
String[] replacedIndices = new String[]{"bar"};
|
||||
assertThat(indices.size(), equalTo(replacedIndices.length));
|
||||
assertThat(request.indices().length, equalTo(replacedIndices.length));
|
||||
assertThat(indices, hasItems(replacedIndices));
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
}
|
||||
|
||||
public void testResolveWildcardsMinusExpandWilcardsOpenAndClosed() {
|
||||
|
@ -174,8 +185,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
|
||||
String[] replacedIndices = new String[]{"bar", "bar-closed"};
|
||||
assertThat(indices.size(), equalTo(replacedIndices.length));
|
||||
assertThat(request.indices().length, equalTo(replacedIndices.length));
|
||||
assertThat(indices, hasItems(replacedIndices));
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
}
|
||||
|
||||
public void testResolveWildcardsPlusAndMinusExpandWilcardsOpen() {
|
||||
|
@ -184,8 +196,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
|
||||
String[] replacedIndices = new String[]{"bar", "barbaz"};
|
||||
assertThat(indices.size(), equalTo(replacedIndices.length));
|
||||
assertThat(request.indices().length, equalTo(replacedIndices.length));
|
||||
assertThat(indices, hasItems(replacedIndices));
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
}
|
||||
|
||||
public void testResolveWildcardsPlusAndMinusExpandWilcardsOpenAndClosed() {
|
||||
|
@ -194,8 +207,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
|
||||
String[] replacedIndices = new String[]{"bar", "bar-closed", "barbaz"};
|
||||
assertThat(indices.size(), equalTo(replacedIndices.length));
|
||||
assertThat(request.indices().length, equalTo(replacedIndices.length));
|
||||
assertThat(indices, hasItems(replacedIndices));
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
}
|
||||
|
||||
public void testResolveNonMatchingIndices() {
|
||||
|
@ -223,6 +237,7 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
|
||||
String[] expectedIndices = new String[]{"bar", "missing"};
|
||||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(request.indices().length, equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
assertThat(request.indices(), equalTo(expectedIndices));
|
||||
}
|
||||
|
@ -253,10 +268,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
String[] expectedIndices = new String[]{"alias1", "alias2", "foo", "foofoo", "foobar"};
|
||||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("foo", "foobar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("foo", "foobar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("alias2"));
|
||||
}
|
||||
|
||||
public void testResolveIndicesAliasesRequestExistingAlias() {
|
||||
|
@ -268,10 +283,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
String[] expectedIndices = new String[]{"alias1", "foofoobar", "foo", "foofoo", "foobar"};
|
||||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("foo", "foobar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("foo", "foobar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("foofoobar"));
|
||||
}
|
||||
|
||||
public void testResolveIndicesAliasesRequestMissingIndex() {
|
||||
|
@ -283,10 +298,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
String[] expectedIndices = new String[]{"alias1", "alias2", "foo", "foofoo", "missing"};
|
||||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("missing"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("missing"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("alias2"));
|
||||
}
|
||||
|
||||
public void testResolveWildcardsIndicesAliasesRequest() {
|
||||
|
@ -299,10 +314,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
//wildcards get replaced on each single action
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("bar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("alias2"));
|
||||
}
|
||||
|
||||
public void testResolveWildcardsIndicesAliasesRequestNoMatchingIndices() {
|
||||
|
@ -330,10 +345,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices, hasItems(expectedIndices));
|
||||
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
|
||||
//_all gets replaced with all indices that user is authorized for, on each single action
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("alias2"));
|
||||
}
|
||||
|
||||
public void testResolveAllIndicesAliasesRequestNoAuthorizedIndices() {
|
||||
|
@ -369,10 +384,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
String[] expectedIndices = new String[]{"foo", "foofoobar", "foofoo", "barbaz"};
|
||||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("foofoo"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("barbaz"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("foofoo"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("barbaz"));
|
||||
}
|
||||
|
||||
public void testResolveIndicesAliasesRequestDeleteActionsMissingIndex() {
|
||||
|
@ -384,10 +399,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
String[] expectedIndices = new String[]{"foo", "foofoobar", "missing_index", "missing_alias"};
|
||||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("missing_index"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("missing_alias"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("missing_index"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("missing_alias"));
|
||||
}
|
||||
|
||||
public void testResolveWildcardsIndicesAliasesRequestDeleteActions() {
|
||||
|
@ -400,10 +415,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
//wildcards get replaced within each single action
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("barbaz"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("bar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("barbaz"));
|
||||
}
|
||||
|
||||
public void testResolveAliasesWildcardsIndicesAliasesRequestDeleteActions() {
|
||||
|
@ -418,10 +433,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
//alias foofoobar on both sides, that's fine, es core would do the same, same as above
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("bar", "foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar", "foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("bar", "foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("bar", "foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("foofoobar"));
|
||||
}
|
||||
|
||||
public void testResolveAllAliasesWildcardsIndicesAliasesRequestDeleteActions() {
|
||||
|
@ -436,10 +451,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
//alias foofoobar on both sides, that's fine, es core would do the same, same as above
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("bar", "foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("bar", "foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("foofoobar", "explicit"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("bar", "foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("bar", "foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("foofoobar", "explicit"));
|
||||
}
|
||||
|
||||
public void testResolveAliasesWildcardsIndicesAliasesRequestDeleteActionsNoAuthorizedIndices() {
|
||||
|
@ -465,10 +480,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
//every single action has its indices replaced with matching (authorized) ones
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foofoobar", "foofoo"));
|
||||
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
|
||||
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("bar"));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("foofoobar"));
|
||||
}
|
||||
|
||||
public void testResolveGetAliasesRequest() {
|
||||
|
@ -478,8 +493,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
String[] expectedIndices = new String[]{"alias1", "foo", "foofoo"};
|
||||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
assertThat(request.indices(), arrayContaining("foo", "foofoo"));
|
||||
assertThat(request.aliases(), arrayContaining("alias1"));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder("foo", "foofoo"));
|
||||
assertThat(request.aliases(), arrayContainingInAnyOrder("alias1"));
|
||||
}
|
||||
|
||||
public void testResolveGetAliasesRequestMissingIndex() {
|
||||
|
@ -491,8 +506,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
String[] expectedIndices = new String[]{"alias2", "missing"};
|
||||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
assertThat(request.indices(), arrayContaining("missing"));
|
||||
assertThat(request.aliases(), arrayContaining("alias2"));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder("missing"));
|
||||
assertThat(request.aliases(), arrayContainingInAnyOrder("alias2"));
|
||||
}
|
||||
|
||||
public void testResolveWildcardsGetAliasesRequest() {
|
||||
|
@ -505,8 +520,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
//wildcards get replaced on each single action
|
||||
assertThat(request.indices(), arrayContaining("foofoobar", "foofoo", "foofoo-closed"));
|
||||
assertThat(request.aliases(), arrayContaining("alias1"));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder("foofoobar", "foofoo", "foofoo-closed"));
|
||||
assertThat(request.aliases(), arrayContainingInAnyOrder("alias1"));
|
||||
}
|
||||
|
||||
public void testResolveWildcardsGetAliasesRequestNoMatchingIndices() {
|
||||
|
@ -536,8 +551,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices, hasItems(expectedIndices));
|
||||
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
|
||||
//_all gets replaced with all indices that user is authorized for
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.aliases(), arrayContaining("alias1"));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
assertThat(request.aliases(), arrayContainingInAnyOrder("alias1"));
|
||||
}
|
||||
|
||||
public void testResolveAllGetAliasesRequestExpandWildcardsOpenOnly() {
|
||||
|
@ -556,8 +571,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices, hasItems(expectedIndices));
|
||||
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
|
||||
//_all gets replaced with all indices that user is authorized for
|
||||
assertThat(request.indices(), arrayContaining(replacedIndices));
|
||||
assertThat(request.aliases(), arrayContaining("alias1"));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
|
||||
assertThat(request.aliases(), arrayContainingInAnyOrder("alias1"));
|
||||
}
|
||||
|
||||
public void testResolveAllGetAliasesRequestNoAuthorizedIndices() {
|
||||
|
@ -600,8 +615,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
//_all gets replaced with all indices that user is authorized for
|
||||
assertThat(request.indices(), arrayContaining(expectedIndices));
|
||||
assertThat(request.aliases(), arrayContaining("foofoobar"));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(expectedIndices));
|
||||
assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar"));
|
||||
}
|
||||
|
||||
public void testResolveAllAndExplicitAliasesGetAliasesRequest() {
|
||||
|
@ -615,8 +630,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
//_all gets replaced with all indices that user is authorized for
|
||||
assertThat(request.indices(), arrayContaining("bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"));
|
||||
assertThat(request.aliases(), arrayContaining("foofoobar", "explicit"));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder("bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"));
|
||||
assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar", "explicit"));
|
||||
}
|
||||
|
||||
public void testResolveAllAndWildcardsAliasesGetAliasesRequest() {
|
||||
|
@ -630,8 +645,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
//_all gets replaced with all indices that user is authorized for
|
||||
assertThat(request.indices(), arrayContaining(expectedIndices));
|
||||
assertThat(request.aliases(), arrayContaining("foofoobar", "foofoobar"));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(expectedIndices));
|
||||
assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar", "foofoobar"));
|
||||
}
|
||||
|
||||
public void testResolveAliasesWildcardsGetAliasesRequest() {
|
||||
|
@ -646,8 +661,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
//alias foofoobar on both sides, that's fine, es core would do the same, same as above
|
||||
assertThat(request.indices(), arrayContaining("bar", "foofoobar"));
|
||||
assertThat(request.aliases(), arrayContaining("foofoobar"));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder("bar", "foofoobar"));
|
||||
assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar"));
|
||||
}
|
||||
|
||||
public void testResolveAliasesWildcardsGetAliasesRequestNoAuthorizedIndices() {
|
||||
|
@ -797,7 +812,33 @@ public class DefaultIndicesResolverTests extends ESTestCase {
|
|||
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
|
||||
assertThat(indices.size(), equalTo(expectedIndices.length));
|
||||
assertThat(indices, hasItems(expectedIndices));
|
||||
assertThat(request.indices(), arrayContaining(expectedIndices));
|
||||
assertThat(request.indices(), arrayContainingInAnyOrder(expectedIndices));
|
||||
}
|
||||
|
||||
public void testXPackUserHasAccessToSecurityIndex() {
|
||||
SearchRequest request = new SearchRequest();
|
||||
Set<String> indices = defaultIndicesResolver.resolve(XPackUser.INSTANCE, SearchAction.NAME, request, metaData);
|
||||
assertThat(indices, hasItem(ShieldTemplateService.SECURITY_INDEX_NAME));
|
||||
|
||||
IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest();
|
||||
aliasesRequest.addAlias("shield_alias", "*");
|
||||
indices = defaultIndicesResolver.resolve(XPackUser.INSTANCE, IndicesAliasesAction.NAME, aliasesRequest, metaData);
|
||||
assertThat(indices, hasItem(ShieldTemplateService.SECURITY_INDEX_NAME));
|
||||
}
|
||||
|
||||
public void testNonXPackUserAccessingSecurityIndex() {
|
||||
User allAccessUser = new User("all_access", new String[] { "all_access" } );
|
||||
when(rolesStore.role("all_access")).thenReturn(
|
||||
Role.builder("all_access").add(IndexPrivilege.ALL, "*").cluster(ClusterPrivilege.ALL).build());
|
||||
|
||||
SearchRequest request = new SearchRequest();
|
||||
Set<String> indices = defaultIndicesResolver.resolve(allAccessUser, SearchAction.NAME, request, metaData);
|
||||
assertThat(indices, not(hasItem(ShieldTemplateService.SECURITY_INDEX_NAME)));
|
||||
|
||||
IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest();
|
||||
aliasesRequest.addAlias("shield_alias1", "*");
|
||||
indices = defaultIndicesResolver.resolve(allAccessUser, IndicesAliasesAction.NAME, aliasesRequest, metaData);
|
||||
assertThat(indices, not(hasItem(ShieldTemplateService.SECURITY_INDEX_NAME)));
|
||||
}
|
||||
|
||||
// TODO with the removal of DeleteByQuery is there another way to test resolving a write action?
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.test;
|
||||
|
||||
import org.elasticsearch.index.IndexNotFoundException;
|
||||
import org.elasticsearch.shield.ShieldTemplateService;
|
||||
import org.elasticsearch.shield.authc.esnative.ESNativeUsersStore;
|
||||
import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore;
|
||||
import org.elasticsearch.shield.client.SecurityClient;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.isOneOf;
|
||||
|
||||
/**
|
||||
* Test case with method to handle the starting and stopping the stores for native users and roles
|
||||
*/
|
||||
public abstract class NativeRealmIntegTestCase extends ShieldIntegTestCase {
|
||||
|
||||
@Before
|
||||
public void ensureNativeStoresStarted() throws Exception {
|
||||
for (ESNativeUsersStore store : internalCluster().getInstances(ESNativeUsersStore.class)) {
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), is(ESNativeUsersStore.State.STARTED));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (ESNativeRolesStore store : internalCluster().getInstances(ESNativeRolesStore.class)) {
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), is(ESNativeRolesStore.State.STARTED));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopESNativeStores() throws Exception {
|
||||
for (ESNativeUsersStore store : internalCluster().getInstances(ESNativeUsersStore.class)) {
|
||||
store.stop();
|
||||
// the store may already be stopping so wait until it is stopped
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), isOneOf(ESNativeUsersStore.State.STOPPED, ESNativeUsersStore.State.FAILED));
|
||||
}
|
||||
});
|
||||
store.reset();
|
||||
}
|
||||
|
||||
for (ESNativeRolesStore store : internalCluster().getInstances(ESNativeRolesStore.class)) {
|
||||
store.stop();
|
||||
// the store may already be stopping so wait until it is stopped
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(store.state(), isOneOf(ESNativeRolesStore.State.STOPPED, ESNativeRolesStore.State.FAILED));
|
||||
}
|
||||
});
|
||||
store.reset();
|
||||
}
|
||||
|
||||
try {
|
||||
// this is a hack to clean up the .security index since only the XPack user can delete it
|
||||
internalClient().admin().indices().prepareDelete(ShieldTemplateService.SECURITY_INDEX_NAME).get();
|
||||
} catch (IndexNotFoundException e) {
|
||||
// ignore it since not all tests create this index...
|
||||
}
|
||||
|
||||
if (getCurrentClusterScope() == Scope.SUITE) {
|
||||
// Clear the realm cache for all realms since we use a SUITE scoped cluster
|
||||
SecurityClient client = securityClient(internalCluster().transportClient());
|
||||
client.prepareClearRealmCache().get();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,15 +12,21 @@ import org.elasticsearch.client.Client;
|
|||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.cluster.health.ClusterHealthStatus;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.IndexNotFoundException;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.shield.InternalClient;
|
||||
import org.elasticsearch.shield.Shield;
|
||||
import org.elasticsearch.shield.ShieldTemplateService;
|
||||
import org.elasticsearch.shield.authc.esnative.ESNativeUsersStore;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore;
|
||||
import org.elasticsearch.shield.client.SecurityClient;
|
||||
import org.elasticsearch.test.ESIntegTestCase.SuppressLocalMode;
|
||||
import org.elasticsearch.test.transport.AssertingLocalTransport;
|
||||
import org.elasticsearch.test.transport.MockTransportService;
|
||||
import org.elasticsearch.xpack.XPackClient;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -38,7 +44,8 @@ import java.util.stream.Collectors;
|
|||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.isOneOf;
|
||||
import static org.hamcrest.core.IsCollectionContaining.hasItem;
|
||||
|
||||
/**
|
||||
|
@ -79,7 +86,7 @@ public abstract class ShieldIntegTestCase extends ESIntegTestCase {
|
|||
return getAnnotation(clazz.getSuperclass());
|
||||
}
|
||||
|
||||
private Scope getCurrentClusterScope() {
|
||||
Scope getCurrentClusterScope() {
|
||||
return getCurrentClusterScope(this.getClass());
|
||||
}
|
||||
|
||||
|
|
|
@ -6,28 +6,43 @@
|
|||
package org.elasticsearch.xpack.test.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
||||
import org.apache.lucene.util.IOUtils;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
import org.elasticsearch.xpack.common.xcontent.XContentUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public abstract class XPackRestTestCase extends ESRestTestCase {
|
||||
|
||||
private static final String BASIC_AUTH_VALUE = basicAuthHeaderValue("test_user", new SecuredString("changeme".toCharArray()));
|
||||
|
||||
public XPackRestTestCase(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
@ -39,14 +54,16 @@ public abstract class XPackRestTestCase extends ESRestTestCase {
|
|||
|
||||
@Before
|
||||
public void startWatcher() throws Exception {
|
||||
try(CloseableHttpClient client = HttpClients.createMinimal(new BasicHttpClientConnectionManager())) {
|
||||
try (CloseableHttpClient client = HttpClients.createMinimal(new BasicHttpClientConnectionManager())) {
|
||||
URL url = getClusterUrls()[0];
|
||||
HttpPut request = new HttpPut(new URI("http",
|
||||
"test_user:changeme",
|
||||
null,
|
||||
url.getHost(),
|
||||
url.getPort(),
|
||||
"/_watcher/_start", null, null));
|
||||
client.execute(request);
|
||||
request.addHeader("Authorization", BASIC_AUTH_VALUE);
|
||||
try (CloseableHttpResponse response = client.execute(request)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,19 +72,65 @@ public abstract class XPackRestTestCase extends ESRestTestCase {
|
|||
try(CloseableHttpClient client = HttpClients.createMinimal(new BasicHttpClientConnectionManager())) {
|
||||
URL url = getClusterUrls()[0];
|
||||
HttpPut request = new HttpPut(new URI("http",
|
||||
"test_user:changeme",
|
||||
null,
|
||||
url.getHost(),
|
||||
url.getPort(),
|
||||
"/_watcher/_stop", null, null));
|
||||
client.execute(request);
|
||||
request.addHeader("Authorization", BASIC_AUTH_VALUE);
|
||||
try (CloseableHttpResponse response = client.execute(request)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearShieldUsersAndRoles() throws Exception {
|
||||
// we cannot delete the .security index from a rest test since we aren't the internal user, lets wipe the data
|
||||
// TODO remove this once the built-in SUPERUSER role is added that can delete the index and we use the built in admin user here
|
||||
try (CloseableHttpClient client = HttpClients.createMinimal(new BasicHttpClientConnectionManager())) {
|
||||
final URL url = getClusterUrls()[0];
|
||||
HttpGet getUsersRequest = new HttpGet(new URI("http", null, url.getHost(), url.getPort(), "/_shield/user", null, null));
|
||||
getUsersRequest.addHeader("Authorization", BASIC_AUTH_VALUE);
|
||||
try (CloseableHttpResponse closeableHttpResponse = client.execute(getUsersRequest)) {
|
||||
assertThat(closeableHttpResponse.getStatusLine().getStatusCode(), is(200));
|
||||
String response = Streams.copyToString(
|
||||
new InputStreamReader(closeableHttpResponse.getEntity().getContent(), StandardCharsets.UTF_8));
|
||||
Map<String, Object> responseMap = XContentFactory.xContent(response).createParser(response).map();
|
||||
|
||||
// in the structure of this API, the users are the keyset
|
||||
for (String user : responseMap.keySet()) {
|
||||
HttpDelete delete = new HttpDelete(new URI("http", null, url.getHost(), url.getPort(),
|
||||
"/_shield/user/" + user, null, null));
|
||||
delete.addHeader("Authorization", BASIC_AUTH_VALUE);
|
||||
try (CloseableHttpResponse deleteResponse = client.execute(delete)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HttpGet getRolesRequest = new HttpGet(new URI("http", null, url.getHost(), url.getPort(), "/_shield/role",
|
||||
null, null));
|
||||
getRolesRequest.addHeader("Authorization", BASIC_AUTH_VALUE);
|
||||
try (CloseableHttpResponse closeableHttpResponse = client.execute(getRolesRequest)) {
|
||||
assertThat(closeableHttpResponse.getStatusLine().getStatusCode(), is(200));
|
||||
String response = Streams.copyToString(
|
||||
new InputStreamReader(closeableHttpResponse.getEntity().getContent(), StandardCharsets.UTF_8));
|
||||
Map<String, Object> responseMap = XContentFactory.xContent(response).createParser(response).map();
|
||||
|
||||
// in the structure of this API, the users are the keyset
|
||||
for (String role : responseMap.keySet()) {
|
||||
HttpDelete delete = new HttpDelete(new URI("http", null, url.getHost(), url.getPort(),
|
||||
"/_shield/role/" + role, null, null));
|
||||
delete.addHeader("Authorization", BASIC_AUTH_VALUE);
|
||||
try (CloseableHttpResponse deleteResponse = client.execute(delete)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Settings restClientSettings() {
|
||||
String token = basicAuthHeaderValue("test_user", new SecuredString("changeme".toCharArray()));
|
||||
return Settings.builder()
|
||||
.put(ThreadContext.PREFIX + ".Authorization", token)
|
||||
.put(ThreadContext.PREFIX + ".Authorization", BASIC_AUTH_VALUE)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue