Merge branch 'master' into cli-parsing

Original commit: elastic/x-pack-elasticsearch@ff525e0e00
This commit is contained in:
Ryan Ernst 2016-03-06 13:33:08 -08:00
commit b54e6a7ae6
14 changed files with 473 additions and 280 deletions

View File

@ -11,7 +11,7 @@ import java.nio.file.Path;
import org.elasticsearch.cli.ExitCodes; import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.UserError; import org.elasticsearch.cli.UserError;
import org.elasticsearch.common.cli.CliToolTestCase; import org.elasticsearch.common.cli.MockTerminal;
import org.elasticsearch.common.cli.Terminal; import org.elasticsearch.common.cli.Terminal;
import org.elasticsearch.license.core.License; import org.elasticsearch.license.core.License;
import org.elasticsearch.license.licensor.TestUtils; import org.elasticsearch.license.licensor.TestUtils;
@ -74,11 +74,12 @@ public class LicenseGenerationToolTests extends ESTestCase {
} }
private String runTool(String licenseSpecString, Path licenseSpecPath) throws Exception { private String runTool(String licenseSpecString, Path licenseSpecPath) throws Exception {
CliToolTestCase.CaptureOutputTerminal outputTerminal = new CliToolTestCase.CaptureOutputTerminal(); MockTerminal outputTerminal = new MockTerminal();
LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool();
licenseGeneratorTool.execute(outputTerminal, pubKeyPath, priKeyPath, licenseSpecString, licenseSpecPath); licenseGeneratorTool.execute(outputTerminal, pubKeyPath, priKeyPath, licenseSpecString, licenseSpecPath);
assertEquals(1, outputTerminal.getTerminalOutput().size()); String output = outputTerminal.getOutput();
return outputTerminal.getTerminalOutput().get(0); assertFalse(output, output.isEmpty());
return output;
} }
} }

View File

@ -175,7 +175,6 @@ integTest {
ant.waitfor(maxwait: '10', maxwaitunit: 'second', checkevery: '100', checkeveryunit: 'millisecond', ant.waitfor(maxwait: '10', maxwaitunit: 'second', checkevery: '100', checkeveryunit: 'millisecond',
timeoutproperty: waitForNodeStartProp) { timeoutproperty: waitForNodeStartProp) {
and { and {
resourcecontains(resource: "${node.startLog.toString()}", substring: "bound_addresses {${node.httpUri()}")
resourcecontains(resource: "${node.startLog.toString()}", substring: 'started') resourcecontains(resource: "${node.startLog.toString()}", substring: 'started')
} }
} }

View File

@ -48,7 +48,8 @@ public class TransportClearRealmCacheAction extends TransportNodesAction<ClearRe
Object resp = responses.get(i); Object resp = responses.get(i);
if (resp instanceof ClearRealmCacheResponse.Node) { if (resp instanceof ClearRealmCacheResponse.Node) {
nodes.add((ClearRealmCacheResponse.Node) resp); 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"); throw new IllegalArgumentException("node response [" + resp.getClass() + "] is not the correct type");
} }
} }

View File

@ -45,7 +45,8 @@ public class TransportClearRolesCacheAction extends TransportNodesAction<ClearRo
Object resp = nodesResponses.get(i); Object resp = nodesResponses.get(i);
if (resp instanceof ClearRolesCacheResponse.Node) { if (resp instanceof ClearRolesCacheResponse.Node) {
responses.add((ClearRolesCacheResponse.Node) resp); 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"); throw new IllegalArgumentException("node response [" + resp.getClass() + "] is not the correct type");
} }
} }

View File

@ -22,6 +22,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.search.action.SearchTransportService; import org.elasticsearch.search.action.SearchTransportService;
import org.elasticsearch.shield.ShieldTemplateService;
import org.elasticsearch.shield.SystemUser; import org.elasticsearch.shield.SystemUser;
import org.elasticsearch.shield.User; import org.elasticsearch.shield.User;
import org.elasticsearch.shield.XPackUser; 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); return Collections.unmodifiableList(indicesAndAliases);
} }
@ -208,6 +216,13 @@ public class InternalAuthorizationService extends AbstractComponent implements A
IndicesAccessControl indicesAccessControl = permission.authorize(action, indexNames, metaData); IndicesAccessControl indicesAccessControl = permission.authorize(action, indexNames, metaData);
if (!indicesAccessControl.isGranted()) { if (!indicesAccessControl.isGranted()) {
throw denial(user, action, request); 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 { } else {
setIndicesAccessControl(indicesAccessControl); setIndicesAccessControl(indicesAccessControl);
} }

View File

@ -166,6 +166,7 @@ public class DefaultIndicesAndAliasesResolver implements IndicesAndAliasesResolv
private List<String> replaceWildcardsWithAuthorizedIndices(String[] indices, IndicesOptions indicesOptions, MetaData metaData, private List<String> replaceWildcardsWithAuthorizedIndices(String[] indices, IndicesOptions indicesOptions, MetaData metaData,
List<String> authorizedIndices) { List<String> authorizedIndices) {
// check for all and return list of authorized indices
if (IndexNameExpressionResolver.isAllIndices(indicesList(indices))) { if (IndexNameExpressionResolver.isAllIndices(indicesList(indices))) {
List<String> visibleIndices = new ArrayList<>(); List<String> visibleIndices = new ArrayList<>();
for (String authorizedIndex : authorizedIndices) { for (String authorizedIndex : authorizedIndices) {

View File

@ -16,17 +16,15 @@ import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.shield.action.role.PutRoleResponse; import org.elasticsearch.shield.action.role.PutRoleResponse;
import org.elasticsearch.shield.action.role.GetRolesResponse; import org.elasticsearch.shield.action.role.GetRolesResponse;
import org.elasticsearch.shield.ShieldTemplateService; 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.SecuredString;
import org.elasticsearch.shield.authc.support.UsernamePasswordToken; import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
import org.elasticsearch.shield.authz.RoleDescriptor; import org.elasticsearch.shield.authz.RoleDescriptor;
import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore; import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore;
import org.elasticsearch.shield.client.SecurityClient; 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.ShieldSettingsSource;
import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.test.rest.client.http.HttpResponse; import org.elasticsearch.test.rest.client.http.HttpResponse;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -35,7 +33,6 @@ import java.util.List;
import static org.hamcrest.Matchers.arrayWithSize; import static org.hamcrest.Matchers.arrayWithSize;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isOneOf;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
/** /**
@ -43,7 +40,7 @@ import static org.hamcrest.Matchers.notNullValue;
* test the cache clearing APIs. * test the cache clearing APIs.
*/ */
@TestLogging("shield.authc.esnative:TRACE,shield.authz.esnative:TRACE,integration:DEBUG") @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; private static String[] roles;
@ -56,29 +53,7 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
} }
@Before @Before
public void setupForTest() throws Exception { public void setupForTests() {
// 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));
}
});
}
SecurityClient c = securityClient(); SecurityClient c = securityClient();
// create roles // create roles
for (String role : roles) { for (String role : roles) {
@ -129,13 +104,11 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
} }
public void testModifyingDocumentsDirectly() throws Exception { public void testModifyingDocumentsDirectly() throws Exception {
Client client = internalCluster().transportClient();
int modifiedRolesCount = randomIntBetween(1, roles.length); int modifiedRolesCount = randomIntBetween(1, roles.length);
List<String> toModify = randomSubsetOf(modifiedRolesCount, roles); List<String> toModify = randomSubsetOf(modifiedRolesCount, roles);
logger.debug("--> modifying roles {} to have run_as", toModify); logger.debug("--> modifying roles {} to have run_as", toModify);
for (String role : 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) .setType(ESNativeRolesStore.ROLE_DOC_TYPE)
.setDoc("run_as", new String[] { role }) .setDoc("run_as", new String[] { role })
.get(); .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 // 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! // 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 useHttp = randomBoolean();
final boolean clearAll = randomBoolean(); final boolean clearAll = randomBoolean();
logger.debug("--> starting to clear roles. using http [{}] clearing all [{}]", useHttp, clearAll); 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 { public void testDeletingRoleDocumentDirectly() throws Exception {
Client client = internalCluster().transportClient(); SecurityClient securityClient = securityClient(internalCluster().transportClient());
SecurityClient securityClient = securityClient(client);
final String role = randomFrom(roles); final String role = randomFrom(roles);
RoleDescriptor[] foundRoles = securityClient.prepareGetRoles().names(role).get().roles(); RoleDescriptor[] foundRoles = securityClient.prepareGetRoles().names(role).get().roles();
assertThat(foundRoles.length, is(1)); assertThat(foundRoles.length, is(1));
logger.debug("--> deleting role [{}]", role); logger.debug("--> deleting role [{}]", role);
DeleteResponse response = client DeleteResponse response = internalClient()
.prepareDelete(ShieldTemplateService.SECURITY_INDEX_NAME, ESNativeRolesStore.ROLE_DOC_TYPE, role).get(); .prepareDelete(ShieldTemplateService.SECURITY_INDEX_NAME, ESNativeRolesStore.ROLE_DOC_TYPE, role).get();
assertThat(response.isFound(), is(true)); 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();
}
}
} }

View File

@ -20,13 +20,10 @@ import org.elasticsearch.shield.action.user.DeleteUserResponse;
import org.elasticsearch.shield.action.user.GetUsersResponse; import org.elasticsearch.shield.action.user.GetUsersResponse;
import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.SecuredString;
import org.elasticsearch.shield.authz.RoleDescriptor; import org.elasticsearch.shield.authz.RoleDescriptor;
import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore;
import org.elasticsearch.shield.authz.permission.Role; import org.elasticsearch.shield.authz.permission.Role;
import org.elasticsearch.shield.client.SecurityClient; 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.ShieldSettingsSource;
import org.junit.After;
import org.junit.Before;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; 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.arrayContaining;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isOneOf;
/** /**
* Tests for the ESNativeUsersStore and ESNativeRolesStore * Tests for the ESNativeUsersStore and ESNativeRolesStore
*/ */
public class ESNativeTests extends ShieldIntegTestCase { public class ESNativeTests extends NativeRealmIntegTestCase {
public void testDeletingNonexistingUserAndRole() throws Exception { public void testDeletingNonexistingUserAndRole() throws Exception {
SecurityClient c = securityClient(); SecurityClient c = securityClient();
@ -390,56 +386,4 @@ public class ESNativeTests extends ShieldIntegTestCase {
.admin().cluster().prepareHealth().get(); .admin().cluster().prepareHealth().get();
assertFalse(response.isTimedOut()); 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();
}
}
} }

View File

@ -16,6 +16,7 @@ import java.util.concurrent.atomic.AtomicReference;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.cli.CliTool; import org.elasticsearch.common.cli.CliTool;
import org.elasticsearch.common.cli.MockTerminal;
import org.elasticsearch.common.cli.Terminal; import org.elasticsearch.common.cli.Terminal;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment; import org.elasticsearch.env.Environment;
@ -30,7 +31,6 @@ import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;
@ -229,12 +229,12 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
final CaptureOutputTerminal terminal = new CaptureOutputTerminal(); MockTerminal terminal = new MockTerminal();
ESUsersTool.Useradd cmd = new ESUsersTool.Useradd(terminal, "user1", SecuredStringTests.build("changeme"), "plugin_admin"); ESUsersTool.Useradd cmd = new ESUsersTool.Useradd(terminal, "user1", SecuredStringTests.build("changeme"), "plugin_admin");
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
assertThat(status, is(CliTool.ExitStatus.OK)); assertThat(status, is(CliTool.ExitStatus.OK));
assertThat(terminal.getTerminalOutput(), hasSize(0)); assertTrue(terminal.getOutput(), terminal.getOutput().isEmpty());
} }
public void testUseraddNonExistantRole() throws Exception { public void testUseraddNonExistantRole() throws Exception {
@ -251,13 +251,12 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
final CaptureOutputTerminal terminal = new CaptureOutputTerminal(); MockTerminal terminal = new MockTerminal();
ESUsersTool.Useradd cmd = new ESUsersTool.Useradd(terminal, "user1", SecuredStringTests.build("changeme"), "plugin_admin_2"); ESUsersTool.Useradd cmd = new ESUsersTool.Useradd(terminal, "user1", SecuredStringTests.build("changeme"), "plugin_admin_2");
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
assertThat(status, is(CliTool.ExitStatus.OK)); assertThat(status, is(CliTool.ExitStatus.OK));
assertThat(terminal.getTerminalOutput(), hasSize(1)); assertThat(terminal.getOutput(), containsString("[plugin_admin_2]"));
assertThat(terminal.getTerminalOutput().get(0), containsString("[plugin_admin_2]"));
} }
public void testUserdelParse() throws Exception { public void testUserdelParse() throws Exception {
@ -319,16 +318,14 @@ public class ESUsersToolTests extends ESTestCase {
.put("shield.authc.realms.esusers.files.users_roles", userRolesFile) .put("shield.authc.realms.esusers.files.users_roles", userRolesFile)
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
CaptureOutputTerminal terminal = new CaptureOutputTerminal(); MockTerminal terminal = new MockTerminal();
ESUsersTool.Userdel cmd = new ESUsersTool.Userdel(terminal, "user2"); ESUsersTool.Userdel cmd = new ESUsersTool.Userdel(terminal, "user2");
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
assertThat(status, is(CliTool.ExitStatus.NO_USER)); assertThat(status, is(CliTool.ExitStatus.NO_USER));
List<String> output = terminal.getTerminalOutput(); assertThat(terminal.getOutput(), startsWith("User [user2] doesn't exist"));
assertThat(output, hasSize(equalTo(1)));
assertThat(output, hasItem(startsWith("User [user2] doesn't exist")));
assertFileExists(userFile); assertFileExists(userFile);
List<String> lines = Files.readAllLines(userFile, StandardCharsets.UTF_8); List<String> lines = Files.readAllLines(userFile, StandardCharsets.UTF_8);
@ -617,12 +614,12 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal(); MockTerminal catchTerminalOutput = new MockTerminal();
ESUsersTool.Roles cmd = new ESUsersTool.Roles(catchTerminalOutput, "user", Strings.EMPTY_ARRAY, Strings.EMPTY_ARRAY); ESUsersTool.Roles cmd = new ESUsersTool.Roles(catchTerminalOutput, "user", Strings.EMPTY_ARRAY, Strings.EMPTY_ARRAY);
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
assertThat(status, is(CliTool.ExitStatus.OK)); assertThat(status, is(CliTool.ExitStatus.OK));
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(allOf(containsString("user"), containsString("user,foo,bar")))); assertThat(catchTerminalOutput.getOutput(), allOf(containsString("user"), containsString("user,foo,bar")));
} }
public void testRolesCmdRoleCanBeAddedWhenUserIsNotInRolesFile() throws Exception { public void testRolesCmdRoleCanBeAddedWhenUserIsNotInRolesFile() throws Exception {
@ -638,7 +635,7 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal(); MockTerminal catchTerminalOutput = new MockTerminal();
ESUsersTool.Roles cmd = new ESUsersTool.Roles(catchTerminalOutput, "user", new String[]{"myrole"}, Strings.EMPTY_ARRAY); ESUsersTool.Roles cmd = new ESUsersTool.Roles(catchTerminalOutput, "user", new String[]{"myrole"}, Strings.EMPTY_ARRAY);
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
@ -675,14 +672,14 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal(); MockTerminal catchTerminalOutput = new MockTerminal();
ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, null); ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, null);
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
assertThat(status, is(CliTool.ExitStatus.OK)); assertThat(status, is(CliTool.ExitStatus.OK));
assertThat(catchTerminalOutput.getTerminalOutput(), hasSize(greaterThanOrEqualTo(2))); String output = catchTerminalOutput.getOutput();
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(containsString("admin"))); assertThat(output, containsString("admin"));
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(allOf(containsString("user"), containsString("user,foo,bar")))); assertThat(output, allOf(containsString("user"), containsString("user,foo,bar")));
} }
public void testListUsersAndRolesCmdListAllUsersWithUnknownRoles() throws Exception { public void testListUsersAndRolesCmdListAllUsersWithUnknownRoles() throws Exception {
@ -695,14 +692,14 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal(); MockTerminal catchTerminalOutput = new MockTerminal();
ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, null); ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, null);
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
assertThat(status, is(CliTool.ExitStatus.OK)); assertThat(status, is(CliTool.ExitStatus.OK));
assertThat(catchTerminalOutput.getTerminalOutput(), hasSize(greaterThanOrEqualTo(2))); String output = catchTerminalOutput.getOutput();
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(containsString("admin"))); assertThat(output, containsString("admin"));
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(allOf(containsString("user"), containsString("user,foo*,bar*")))); assertThat(output, allOf(containsString("user"), containsString("user,foo*,bar*")));
} }
public void testListUsersAndRolesCmdListSingleUser() throws Exception { public void testListUsersAndRolesCmdListSingleUser() throws Exception {
@ -717,14 +714,13 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal(); MockTerminal catchTerminalOutput = new MockTerminal();
ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, "admin"); ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, "admin");
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
assertThat(status, is(CliTool.ExitStatus.OK)); assertThat(status, is(CliTool.ExitStatus.OK));
assertThat(catchTerminalOutput.getTerminalOutput(), hasSize(greaterThanOrEqualTo(1))); assertThat(catchTerminalOutput.getOutput(), containsString("admin"));
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(containsString("admin"))); assertThat(catchTerminalOutput.getOutput(), not(containsString("user")));
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(not(containsString("user"))));
} }
public void testListUsersAndRolesCmdNoUsers() throws Exception { public void testListUsersAndRolesCmdNoUsers() throws Exception {
@ -737,14 +733,12 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
CaptureOutputTerminal terminal = new CaptureOutputTerminal(); MockTerminal terminal = new MockTerminal();
ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(terminal, null); ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(terminal, null);
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
assertThat(status, is(CliTool.ExitStatus.OK)); assertThat(status, is(CliTool.ExitStatus.OK));
List<String> output = terminal.getTerminalOutput(); assertThat(terminal.getOutput(), equalTo("No users found\n"));
assertThat(output, hasSize(1));
assertThat(output.get(0), equalTo("No users found" + System.lineSeparator()));
} }
public void testListUsersAndRolesCmdListSingleUserNotFound() throws Exception { public void testListUsersAndRolesCmdListSingleUserNotFound() throws Exception {
@ -755,7 +749,7 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal(); MockTerminal catchTerminalOutput = new MockTerminal();
ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, "does-not-exist"); ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, "does-not-exist");
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
@ -774,15 +768,15 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal(); MockTerminal catchTerminalOutput = new MockTerminal();
ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, null); ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, null);
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
assertThat(status, is(CliTool.ExitStatus.OK)); assertThat(status, is(CliTool.ExitStatus.OK));
assertThat(catchTerminalOutput.getTerminalOutput(), hasSize(greaterThanOrEqualTo(3))); String output = catchTerminalOutput.getOutput();
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(containsString("admin"))); assertThat(output, containsString("admin"));
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(allOf(containsString("user"), containsString("user,foo,bar")))); assertThat(output, allOf(containsString("user"), containsString("user,foo,bar")));
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(allOf(containsString("no-roles-user"), containsString("-")))); assertThat(output, allOf(containsString("no-roles-user"), containsString("-")));
} }
public void testListUsersAndRolesCmdUsersWithoutRolesAreListed() throws Exception { public void testListUsersAndRolesCmdUsersWithoutRolesAreListed() throws Exception {
@ -797,15 +791,15 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal(); MockTerminal catchTerminalOutput = new MockTerminal();
ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, null); ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, null);
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
assertThat(status, is(CliTool.ExitStatus.OK)); assertThat(status, is(CliTool.ExitStatus.OK));
assertThat(catchTerminalOutput.getTerminalOutput(), hasSize(greaterThanOrEqualTo(3))); String output = catchTerminalOutput.getOutput();
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(allOf(containsString("admin"), containsString("-")))); assertThat(output, allOf(containsString("admin"), containsString("-")));
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(allOf(containsString("user"), containsString("-")))); assertThat(output, allOf(containsString("user"), containsString("-")));
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(allOf(containsString("no-roles-user"), containsString("-")))); assertThat(output, allOf(containsString("no-roles-user"), containsString("-")));
} }
public void testListUsersAndRolesCmdUsersWithoutRolesAreListedForSingleUser() throws Exception { public void testListUsersAndRolesCmdUsersWithoutRolesAreListedForSingleUser() throws Exception {
@ -818,13 +812,12 @@ public class ESUsersToolTests extends ESTestCase {
.put("path.home", createTempDir()) .put("path.home", createTempDir())
.build(); .build();
CaptureOutputTerminal loggingTerminal = new CaptureOutputTerminal(); MockTerminal loggingTerminal = new MockTerminal();
ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(loggingTerminal, "admin"); ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(loggingTerminal, "admin");
CliTool.ExitStatus status = execute(cmd, settings); CliTool.ExitStatus status = execute(cmd, settings);
assertThat(status, is(CliTool.ExitStatus.OK)); assertThat(status, is(CliTool.ExitStatus.OK));
assertThat(loggingTerminal.getTerminalOutput(), hasSize(greaterThanOrEqualTo(1))); assertThat(loggingTerminal.getOutput(), allOf(containsString("admin"), containsString("-")));
assertThat(loggingTerminal.getTerminalOutput(), hasItem(allOf(containsString("admin"), containsString("-"))));
} }
public void testUseraddUsernameWithPeriod() throws Exception { public void testUseraddUsernameWithPeriod() throws Exception {

View File

@ -7,26 +7,43 @@ package org.elasticsearch.shield.authz;
import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.Version; 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.Alias;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesAction; 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.CreateIndexAction;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest; 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.ClearScrollAction;
import org.elasticsearch.action.search.ClearScrollRequest; import org.elasticsearch.action.search.ClearScrollRequest;
import org.elasticsearch.action.search.SearchAction; import org.elasticsearch.action.search.SearchAction;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchScrollAction; import org.elasticsearch.action.search.SearchScrollAction;
import org.elasticsearch.action.search.SearchScrollRequest; 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.ClusterService;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.search.action.SearchTransportService; import org.elasticsearch.search.action.SearchTransportService;
import org.elasticsearch.shield.ShieldTemplateService;
import org.elasticsearch.shield.SystemUser; import org.elasticsearch.shield.SystemUser;
import org.elasticsearch.shield.User; import org.elasticsearch.shield.User;
import org.elasticsearch.shield.XPackUser;
import org.elasticsearch.shield.audit.AuditTrail; import org.elasticsearch.shield.audit.AuditTrail;
import org.elasticsearch.shield.authc.AnonymousService; import org.elasticsearch.shield.authc.AnonymousService;
import org.elasticsearch.shield.authc.DefaultAuthenticationFailureHandler; import org.elasticsearch.shield.authc.DefaultAuthenticationFailureHandler;
@ -40,6 +57,7 @@ import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportRequest; import org.elasticsearch.transport.TransportRequest;
import org.junit.Before; import org.junit.Before;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.elasticsearch.test.ShieldTestsUtils.assertAuthenticationException; import static org.elasticsearch.test.ShieldTestsUtils.assertAuthenticationException;
@ -452,4 +470,84 @@ public class InternalAuthorizationServiceTests extends ESTestCase {
verify(auditTrail).accessGranted(user, "indices:a", request); verify(auditTrail).accessGranted(user, "indices:a", request);
verifyNoMoreInteractions(auditTrail); 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);
}
}
} }

View File

@ -6,6 +6,8 @@
package org.elasticsearch.shield.authz.indicesresolver; package org.elasticsearch.shield.authz.indicesresolver;
import org.elasticsearch.Version; 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.IndicesAliasesAction;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesAction; 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.search.SearchRequest;
import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.Requests; 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.AliasAction;
import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.shield.ShieldTemplateService;
import org.elasticsearch.shield.User; 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.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.junit.Before; import org.junit.Before;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set; 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.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
public class DefaultIndicesResolverTests extends ESTestCase { public class DefaultIndicesResolverTests extends ESTestCase {
private User user; private User user;
private User userNoIndices; private User userNoIndices;
private RolesStore rolesStore;
private MetaData metaData; private MetaData metaData;
private DefaultIndicesAndAliasesResolver defaultIndicesResolver; private DefaultIndicesAndAliasesResolver defaultIndicesResolver;
@ -66,35 +82,23 @@ public class DefaultIndicesResolverTests extends ESTestCase {
.put(indexBuilder("foofoo").putAlias(AliasMetaData.builder("barbaz")).settings(settings)) .put(indexBuilder("foofoo").putAlias(AliasMetaData.builder("barbaz")).settings(settings))
.put(indexBuilder("bar").settings(settings)) .put(indexBuilder("bar").settings(settings))
.put(indexBuilder("bar-closed").state(IndexMetaData.State.CLOSE).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(); metaData = mdBuilder.build();
AuthorizationService authzService = mock(AuthorizationService.class);
user = new User("user", "role"); 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"); userNoIndices = new User("test", "test");
when(authzService.authorizedIndicesAndAliases(userNoIndices, IndicesAliasesAction.NAME)) rolesStore = mock(RolesStore.class);
.thenReturn(Collections.<String>emptyList()); String[] authorizedIndices = new String[] { "bar", "bar-closed", "foofoobar", "foofoo", "missing", "foofoo-closed" };
when(authzService.authorizedIndicesAndAliases(userNoIndices, GetAliasesAction.NAME)) when(rolesStore.role("role")).thenReturn(Role.builder("role").add(IndexPrivilege.ALL, authorizedIndices).build());
.thenReturn(Collections.<String>emptyList()); when(rolesStore.role("test")).thenReturn(Role.builder("test").cluster(ClusterPrivilege.MONITOR).build());
when(authzService.authorizedIndicesAndAliases(userNoIndices, SearchAction.NAME)) ClusterService clusterService = mock(ClusterService.class);
.thenReturn(Collections.<String>emptyList()); ClusterState state = mock(ClusterState.class);
when(authzService.authorizedIndicesAndAliases(userNoIndices, MultiSearchAction.NAME)) when(clusterService.state()).thenReturn(state);
.thenReturn(Collections.<String>emptyList()); 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); defaultIndicesResolver = new DefaultIndicesAndAliasesResolver(authzService);
} }
@ -104,8 +108,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
} }
public void testResolveEmptyIndicesExpandWilcardsOpen() { public void testResolveEmptyIndicesExpandWilcardsOpen() {
@ -114,8 +119,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"}; String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
} }
public void testResolveAllExpandWilcardsOpenAndClosed() { public void testResolveAllExpandWilcardsOpenAndClosed() {
@ -124,8 +130,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
} }
public void testResolveAllExpandWilcardsOpen() { public void testResolveAllExpandWilcardsOpen() {
@ -134,8 +141,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"}; String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
} }
public void testResolveWildcardsExpandWilcardsOpenAndClosed() { public void testResolveWildcardsExpandWilcardsOpenAndClosed() {
@ -144,8 +152,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo", "foofoo-closed"}; String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
} }
public void testResolveWildcardsExpandWilcardsOpen() { public void testResolveWildcardsExpandWilcardsOpen() {
@ -154,8 +163,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo"}; String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
} }
public void testResolveWildcardsMinusExpandWilcardsOpen() { public void testResolveWildcardsMinusExpandWilcardsOpen() {
@ -164,8 +174,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
String[] replacedIndices = new String[]{"bar"}; String[] replacedIndices = new String[]{"bar"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
} }
public void testResolveWildcardsMinusExpandWilcardsOpenAndClosed() { public void testResolveWildcardsMinusExpandWilcardsOpenAndClosed() {
@ -174,8 +185,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
String[] replacedIndices = new String[]{"bar", "bar-closed"}; String[] replacedIndices = new String[]{"bar", "bar-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
} }
public void testResolveWildcardsPlusAndMinusExpandWilcardsOpen() { public void testResolveWildcardsPlusAndMinusExpandWilcardsOpen() {
@ -184,8 +196,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
String[] replacedIndices = new String[]{"bar", "barbaz"}; String[] replacedIndices = new String[]{"bar", "barbaz"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
} }
public void testResolveWildcardsPlusAndMinusExpandWilcardsOpenAndClosed() { public void testResolveWildcardsPlusAndMinusExpandWilcardsOpenAndClosed() {
@ -194,8 +207,9 @@ public class DefaultIndicesResolverTests extends ESTestCase {
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
String[] replacedIndices = new String[]{"bar", "bar-closed", "barbaz"}; String[] replacedIndices = new String[]{"bar", "bar-closed", "barbaz"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
} }
public void testResolveNonMatchingIndices() { public void testResolveNonMatchingIndices() {
@ -223,6 +237,7 @@ public class DefaultIndicesResolverTests extends ESTestCase {
Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
String[] expectedIndices = new String[]{"bar", "missing"}; String[] expectedIndices = new String[]{"bar", "missing"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(request.indices().length, equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.indices(), equalTo(expectedIndices)); assertThat(request.indices(), equalTo(expectedIndices));
} }
@ -253,10 +268,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
String[] expectedIndices = new String[]{"alias1", "alias2", "foo", "foofoo", "foobar"}; String[] expectedIndices = new String[]{"alias1", "alias2", "foo", "foofoo", "foobar"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo", "foofoo")); assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1")); assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("foo", "foobar")); assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("foo", "foobar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2")); assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("alias2"));
} }
public void testResolveIndicesAliasesRequestExistingAlias() { public void testResolveIndicesAliasesRequestExistingAlias() {
@ -268,10 +283,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
String[] expectedIndices = new String[]{"alias1", "foofoobar", "foo", "foofoo", "foobar"}; String[] expectedIndices = new String[]{"alias1", "foofoobar", "foo", "foofoo", "foobar"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo", "foofoo")); assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1")); assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("foo", "foobar")); assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("foo", "foobar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("foofoobar")); assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("foofoobar"));
} }
public void testResolveIndicesAliasesRequestMissingIndex() { public void testResolveIndicesAliasesRequestMissingIndex() {
@ -283,10 +298,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
String[] expectedIndices = new String[]{"alias1", "alias2", "foo", "foofoo", "missing"}; String[] expectedIndices = new String[]{"alias1", "alias2", "foo", "foofoo", "missing"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo", "foofoo")); assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1")); assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("missing")); assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("missing"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2")); assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("alias2"));
} }
public void testResolveWildcardsIndicesAliasesRequest() { public void testResolveWildcardsIndicesAliasesRequest() {
@ -299,10 +314,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
//wildcards get replaced on each single action //wildcards get replaced on each single action
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foofoobar", "foofoo")); assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foofoobar", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1")); assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar")); assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("bar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2")); assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("alias2"));
} }
public void testResolveWildcardsIndicesAliasesRequestNoMatchingIndices() { public void testResolveWildcardsIndicesAliasesRequestNoMatchingIndices() {
@ -330,10 +345,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"}; String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
//_all gets replaced with all indices that user is authorized for, on each single action //_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).indices(), arrayContainingInAnyOrder(replacedIndices));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1")); assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining(replacedIndices)); assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder(replacedIndices));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2")); assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("alias2"));
} }
public void testResolveAllIndicesAliasesRequestNoAuthorizedIndices() { public void testResolveAllIndicesAliasesRequestNoAuthorizedIndices() {
@ -369,10 +384,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
String[] expectedIndices = new String[]{"foo", "foofoobar", "foofoo", "barbaz"}; String[] expectedIndices = new String[]{"foo", "foofoobar", "foofoo", "barbaz"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo")); assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar")); assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("foofoo")); assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("foofoo"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("barbaz")); assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("barbaz"));
} }
public void testResolveIndicesAliasesRequestDeleteActionsMissingIndex() { public void testResolveIndicesAliasesRequestDeleteActionsMissingIndex() {
@ -384,10 +399,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
String[] expectedIndices = new String[]{"foo", "foofoobar", "missing_index", "missing_alias"}; String[] expectedIndices = new String[]{"foo", "foofoobar", "missing_index", "missing_alias"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo")); assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar")); assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("missing_index")); assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("missing_index"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("missing_alias")); assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("missing_alias"));
} }
public void testResolveWildcardsIndicesAliasesRequestDeleteActions() { public void testResolveWildcardsIndicesAliasesRequestDeleteActions() {
@ -400,10 +415,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
//wildcards get replaced within each single action //wildcards get replaced within each single action
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foofoobar", "foofoo")); assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foofoobar", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar")); assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar")); assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("bar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("barbaz")); assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("barbaz"));
} }
public void testResolveAliasesWildcardsIndicesAliasesRequestDeleteActions() { public void testResolveAliasesWildcardsIndicesAliasesRequestDeleteActions() {
@ -418,10 +433,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
//alias foofoobar on both sides, that's fine, es core would do the same, same as above //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).indices(), arrayContainingInAnyOrder("bar", "foofoobar", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar")); assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar", "foofoobar")); assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("bar", "foofoobar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("foofoobar")); assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("foofoobar"));
} }
public void testResolveAllAliasesWildcardsIndicesAliasesRequestDeleteActions() { public void testResolveAllAliasesWildcardsIndicesAliasesRequestDeleteActions() {
@ -436,10 +451,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
//alias foofoobar on both sides, that's fine, es core would do the same, same as above //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).indices(), arrayContainingInAnyOrder("bar", "foofoobar", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar")); assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("bar", "foofoobar", "foofoo")); assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("bar", "foofoobar", "foofoo"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("foofoobar", "explicit")); assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("foofoobar", "explicit"));
} }
public void testResolveAliasesWildcardsIndicesAliasesRequestDeleteActionsNoAuthorizedIndices() { public void testResolveAliasesWildcardsIndicesAliasesRequestDeleteActionsNoAuthorizedIndices() {
@ -465,10 +480,10 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
//every single action has its indices replaced with matching (authorized) ones //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).indices(), arrayContainingInAnyOrder("foofoobar", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar")); assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar")); assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("bar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("foofoobar")); assertThat(request.getAliasActions().get(1).aliases(), arrayContainingInAnyOrder("foofoobar"));
} }
public void testResolveGetAliasesRequest() { public void testResolveGetAliasesRequest() {
@ -478,8 +493,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
String[] expectedIndices = new String[]{"alias1", "foo", "foofoo"}; String[] expectedIndices = new String[]{"alias1", "foo", "foofoo"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.indices(), arrayContaining("foo", "foofoo")); assertThat(request.indices(), arrayContainingInAnyOrder("foo", "foofoo"));
assertThat(request.aliases(), arrayContaining("alias1")); assertThat(request.aliases(), arrayContainingInAnyOrder("alias1"));
} }
public void testResolveGetAliasesRequestMissingIndex() { public void testResolveGetAliasesRequestMissingIndex() {
@ -491,8 +506,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
String[] expectedIndices = new String[]{"alias2", "missing"}; String[] expectedIndices = new String[]{"alias2", "missing"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.indices(), arrayContaining("missing")); assertThat(request.indices(), arrayContainingInAnyOrder("missing"));
assertThat(request.aliases(), arrayContaining("alias2")); assertThat(request.aliases(), arrayContainingInAnyOrder("alias2"));
} }
public void testResolveWildcardsGetAliasesRequest() { public void testResolveWildcardsGetAliasesRequest() {
@ -505,8 +520,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
//wildcards get replaced on each single action //wildcards get replaced on each single action
assertThat(request.indices(), arrayContaining("foofoobar", "foofoo", "foofoo-closed")); assertThat(request.indices(), arrayContainingInAnyOrder("foofoobar", "foofoo", "foofoo-closed"));
assertThat(request.aliases(), arrayContaining("alias1")); assertThat(request.aliases(), arrayContainingInAnyOrder("alias1"));
} }
public void testResolveWildcardsGetAliasesRequestNoMatchingIndices() { public void testResolveWildcardsGetAliasesRequestNoMatchingIndices() {
@ -536,8 +551,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
//_all gets replaced with all indices that user is authorized for //_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
assertThat(request.aliases(), arrayContaining("alias1")); assertThat(request.aliases(), arrayContainingInAnyOrder("alias1"));
} }
public void testResolveAllGetAliasesRequestExpandWildcardsOpenOnly() { public void testResolveAllGetAliasesRequestExpandWildcardsOpenOnly() {
@ -556,8 +571,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"}; String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
//_all gets replaced with all indices that user is authorized for //_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
assertThat(request.aliases(), arrayContaining("alias1")); assertThat(request.aliases(), arrayContainingInAnyOrder("alias1"));
} }
public void testResolveAllGetAliasesRequestNoAuthorizedIndices() { public void testResolveAllGetAliasesRequestNoAuthorizedIndices() {
@ -600,8 +615,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
//_all gets replaced with all indices that user is authorized for //_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContaining(expectedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(expectedIndices));
assertThat(request.aliases(), arrayContaining("foofoobar")); assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar"));
} }
public void testResolveAllAndExplicitAliasesGetAliasesRequest() { public void testResolveAllAndExplicitAliasesGetAliasesRequest() {
@ -615,8 +630,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
//_all gets replaced with all indices that user is authorized for //_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContaining("bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed")); assertThat(request.indices(), arrayContainingInAnyOrder("bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"));
assertThat(request.aliases(), arrayContaining("foofoobar", "explicit")); assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar", "explicit"));
} }
public void testResolveAllAndWildcardsAliasesGetAliasesRequest() { public void testResolveAllAndWildcardsAliasesGetAliasesRequest() {
@ -630,8 +645,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
//_all gets replaced with all indices that user is authorized for //_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContaining(expectedIndices)); assertThat(request.indices(), arrayContainingInAnyOrder(expectedIndices));
assertThat(request.aliases(), arrayContaining("foofoobar", "foofoobar")); assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar", "foofoobar"));
} }
public void testResolveAliasesWildcardsGetAliasesRequest() { public void testResolveAliasesWildcardsGetAliasesRequest() {
@ -646,8 +661,8 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
//alias foofoobar on both sides, that's fine, es core would do the same, same as above //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.indices(), arrayContainingInAnyOrder("bar", "foofoobar"));
assertThat(request.aliases(), arrayContaining("foofoobar")); assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar"));
} }
public void testResolveAliasesWildcardsGetAliasesRequestNoAuthorizedIndices() { public void testResolveAliasesWildcardsGetAliasesRequestNoAuthorizedIndices() {
@ -797,7 +812,33 @@ public class DefaultIndicesResolverTests extends ESTestCase {
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); 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? // TODO with the removal of DeleteByQuery is there another way to test resolving a write action?

View File

@ -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();
}
}
}

View File

@ -12,15 +12,21 @@ import org.elasticsearch.client.Client;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.shield.InternalClient; 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.authc.support.SecuredString;
import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore;
import org.elasticsearch.shield.client.SecurityClient; import org.elasticsearch.shield.client.SecurityClient;
import org.elasticsearch.test.ESIntegTestCase.SuppressLocalMode; import org.elasticsearch.test.ESIntegTestCase.SuppressLocalMode;
import org.elasticsearch.test.transport.AssertingLocalTransport; import org.elasticsearch.test.transport.AssertingLocalTransport;
import org.elasticsearch.test.transport.MockTransportService; import org.elasticsearch.test.transport.MockTransportService;
import org.elasticsearch.xpack.XPackClient; import org.elasticsearch.xpack.XPackClient;
import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.xpack.XPackPlugin;
import org.junit.After;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; 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.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout; 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; import static org.hamcrest.core.IsCollectionContaining.hasItem;
/** /**
@ -79,7 +86,7 @@ public abstract class ShieldIntegTestCase extends ESIntegTestCase {
return getAnnotation(clazz.getSuperclass()); return getAnnotation(clazz.getSuperclass());
} }
private Scope getCurrentClusterScope() { Scope getCurrentClusterScope() {
return getCurrentClusterScope(this.getClass()); return getCurrentClusterScope(this.getClass());
} }

View File

@ -6,28 +6,43 @@
package org.elasticsearch.xpack.test.rest; package org.elasticsearch.xpack.test.rest;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; 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.client.methods.HttpPut;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager; 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.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext; 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.shield.authc.support.SecuredString;
import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.RestTestCandidate; import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException; import org.elasticsearch.test.rest.parser.RestTestParseException;
import org.elasticsearch.xpack.common.xcontent.XContentUtils;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue; import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
import static org.hamcrest.Matchers.is;
public abstract class XPackRestTestCase extends ESRestTestCase { 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) { public XPackRestTestCase(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate); super(testCandidate);
} }
@ -39,14 +54,16 @@ public abstract class XPackRestTestCase extends ESRestTestCase {
@Before @Before
public void startWatcher() throws Exception { public void startWatcher() throws Exception {
try(CloseableHttpClient client = HttpClients.createMinimal(new BasicHttpClientConnectionManager())) { try (CloseableHttpClient client = HttpClients.createMinimal(new BasicHttpClientConnectionManager())) {
URL url = getClusterUrls()[0]; URL url = getClusterUrls()[0];
HttpPut request = new HttpPut(new URI("http", HttpPut request = new HttpPut(new URI("http",
"test_user:changeme", null,
url.getHost(), url.getHost(),
url.getPort(), url.getPort(),
"/_watcher/_start", null, null)); "/_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())) { try(CloseableHttpClient client = HttpClients.createMinimal(new BasicHttpClientConnectionManager())) {
URL url = getClusterUrls()[0]; URL url = getClusterUrls()[0];
HttpPut request = new HttpPut(new URI("http", HttpPut request = new HttpPut(new URI("http",
"test_user:changeme", null,
url.getHost(), url.getHost(),
url.getPort(), url.getPort(),
"/_watcher/_stop", null, null)); "/_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 @Override
protected Settings restClientSettings() { protected Settings restClientSettings() {
String token = basicAuthHeaderValue("test_user", new SecuredString("changeme".toCharArray()));
return Settings.builder() return Settings.builder()
.put(ThreadContext.PREFIX + ".Authorization", token) .put(ThreadContext.PREFIX + ".Authorization", BASIC_AUTH_VALUE)
.build(); .build();
} }
} }