Merge branch 'master' of https://github.com/elasticsearch/elasticsearch-shield into doc-feedback
Conflicts: docs/public/02-architecture.asciidoc docs/public/04-authorization.asciidoc docs/public/07-securing-nodes.asciidoc docs/public/clients/kibana.asciidoc docs/public/clients/logstash.asciidoc docs/public/clients/marvel.asciidoc Original commit: elastic/x-pack-elasticsearch@57efef1bf6
This commit is contained in:
commit
647e545c79
|
@ -11,16 +11,19 @@ import org.elasticsearch.common.cli.CliTool;
|
|||
import org.elasticsearch.common.cli.CliToolConfig;
|
||||
import org.elasticsearch.common.cli.Terminal;
|
||||
import org.elasticsearch.common.cli.commons.CommandLine;
|
||||
import org.elasticsearch.common.collect.Lists;
|
||||
import org.elasticsearch.common.collect.Maps;
|
||||
import org.elasticsearch.common.collect.ObjectArrays;
|
||||
import org.elasticsearch.common.collect.Sets;
|
||||
import org.elasticsearch.common.collect.*;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.authc.esusers.FileUserPasswdStore;
|
||||
import org.elasticsearch.shield.authc.esusers.FileUserRolesStore;
|
||||
import org.elasticsearch.shield.authc.support.Hasher;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authz.AuthorizationException;
|
||||
import org.elasticsearch.shield.authz.AuthorizationService;
|
||||
import org.elasticsearch.shield.authz.Permission;
|
||||
import org.elasticsearch.shield.authz.store.FileRolesStore;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
@ -118,6 +121,7 @@ public class ESUsersTool extends CliTool {
|
|||
|
||||
@Override
|
||||
public ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
verifyRoles(terminal, settings, env, roles);
|
||||
Path file = FileUserPasswdStore.resolveFile(settings, env);
|
||||
Map<String, char[]> users = new HashMap<>(FileUserPasswdStore.parseFile(file, null));
|
||||
if (users.containsKey(username)) {
|
||||
|
@ -168,8 +172,6 @@ public class ESUsersTool extends CliTool {
|
|||
char[] passwd = users.remove(username);
|
||||
if (passwd != null) {
|
||||
FileUserPasswdStore.writeFile(users, file);
|
||||
} else {
|
||||
terminal.println("Warning: users file [%s] did not contain password entry for user [%s]", file.toAbsolutePath(), username);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,8 +181,6 @@ public class ESUsersTool extends CliTool {
|
|||
String[] roles = userRoles.remove(username);
|
||||
if (roles != null) {
|
||||
FileUserRolesStore.writeFile(userRoles, file);
|
||||
} else {
|
||||
terminal.println("Warning: users_roles file [%s] did not contain roles entry for user [%s]", file.toAbsolutePath(), username);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,6 +311,7 @@ public class ESUsersTool extends CliTool {
|
|||
if (userRoles.get(username) != null) {
|
||||
roles.addAll(Arrays.asList(userRoles.get(username)));
|
||||
}
|
||||
verifyRoles(terminal, settings, env, addRoles);
|
||||
roles.addAll(Arrays.asList(addRoles));
|
||||
roles.removeAll(Arrays.asList(removeRoles));
|
||||
|
||||
|
@ -347,6 +348,7 @@ public class ESUsersTool extends CliTool {
|
|||
|
||||
@Override
|
||||
public ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
ImmutableMap<String, Permission.Global> knownRoles = loadRoles(terminal, settings, env);
|
||||
Path userRolesFilePath = FileUserRolesStore.resolveFile(settings, env);
|
||||
Map<String, String[]> userRoles = FileUserRolesStore.parseFile(userRolesFilePath, null);
|
||||
Path userFilePath = FileUserPasswdStore.resolveFile(settings, env);
|
||||
|
@ -359,13 +361,27 @@ public class ESUsersTool extends CliTool {
|
|||
}
|
||||
|
||||
if (userRoles.containsKey(username)) {
|
||||
terminal.println("%-15s: %s", username, Joiner.on(",").useForNull("-").join(userRoles.get(username)));
|
||||
String[] roles = userRoles.get(username);
|
||||
Set<String> unknownRoles = Sets.difference(Sets.newHashSet(roles), knownRoles.keySet());
|
||||
String[] markedRoles = markUnknownRoles(roles, unknownRoles);
|
||||
terminal.println("%-15s: %s", username, Joiner.on(",").useForNull("-").join(markedRoles));
|
||||
if (!unknownRoles.isEmpty()) {
|
||||
// at least one role is marked... so printing the legend
|
||||
Path rolesFile = FileRolesStore.resolveFile(settings, env).toAbsolutePath();
|
||||
terminal.println();
|
||||
terminal.println(" [*] An unknown role. Please check [%s] to see available roles", rolesFile.toAbsolutePath());
|
||||
}
|
||||
} else {
|
||||
terminal.println("%-15s: -", username);
|
||||
}
|
||||
} else {
|
||||
boolean unknownRolesFound = false;
|
||||
for (Map.Entry<String, String[]> entry : userRoles.entrySet()) {
|
||||
terminal.println("%-15s: %s", entry.getKey(), Joiner.on(",").join(entry.getValue()));
|
||||
String[] roles = entry.getValue();
|
||||
Set<String> unknownRoles = Sets.difference(Sets.newHashSet(roles), knownRoles.keySet());
|
||||
String[] markedRoles = markUnknownRoles(roles, unknownRoles);
|
||||
terminal.println("%-15s: %s", entry.getKey(), Joiner.on(",").join(markedRoles));
|
||||
unknownRolesFound = unknownRolesFound || !unknownRoles.isEmpty();
|
||||
}
|
||||
// list users without roles
|
||||
Set<String> usersWithoutRoles = Sets.newHashSet(users);
|
||||
|
@ -374,9 +390,67 @@ public class ESUsersTool extends CliTool {
|
|||
terminal.println("%-15s: -", user);
|
||||
}
|
||||
}
|
||||
if (unknownRolesFound) {
|
||||
// at least one role is marked... so printing the legend
|
||||
Path rolesFile = FileRolesStore.resolveFile(settings, env).toAbsolutePath();
|
||||
terminal.println();
|
||||
terminal.println(" [*] An unknown role. Please check [%s] to see available roles", rolesFile.toAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
return ExitStatus.OK;
|
||||
}
|
||||
}
|
||||
|
||||
private static ImmutableMap<String, Permission.Global> loadRoles(Terminal terminal, Settings settings, Environment env) {
|
||||
Path rolesFile = FileRolesStore.resolveFile(settings, env);
|
||||
try {
|
||||
return FileRolesStore.parseFile(rolesFile, null, new DummyAuthzService());
|
||||
} catch (Throwable t) {
|
||||
// if for some reason, parsing fails (malformatted perhaps) we just warn
|
||||
terminal.println("Warning: Could not parse [%s] for roles verification. Please revise and fix it. Nonetheless, the user will still be associated with all specified roles", rolesFile.toAbsolutePath());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String[] markUnknownRoles(String[] roles, Set<String> unknownRoles) {
|
||||
if (unknownRoles.isEmpty()) {
|
||||
return roles;
|
||||
}
|
||||
String[] marked = new String[roles.length];
|
||||
for (int i = 0; i < roles.length; i++) {
|
||||
if (unknownRoles.contains(roles[i])) {
|
||||
marked[i] = roles[i] + "*";
|
||||
} else {
|
||||
marked[i] = roles[i];
|
||||
}
|
||||
}
|
||||
return marked;
|
||||
}
|
||||
|
||||
private static void verifyRoles(Terminal terminal, Settings settings, Environment env, String[] roles) {
|
||||
ImmutableMap<String, Permission.Global> knownRoles = loadRoles(terminal, settings, env);
|
||||
if (knownRoles == null) {
|
||||
return;
|
||||
}
|
||||
Set<String> unknownRoles = Sets.difference(Sets.newHashSet(roles), knownRoles.keySet());
|
||||
if (!unknownRoles.isEmpty()) {
|
||||
Path rolesFile = FileRolesStore.resolveFile(settings, env);
|
||||
terminal.println("Warning: The following roles [%s] are unknown. Make sure to add them to the [%s] file. " +
|
||||
"Nonetheless the user will still be associated with all specified roles",
|
||||
Strings.collectionToCommaDelimitedString(unknownRoles), rolesFile.toAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
private static class DummyAuthzService implements AuthorizationService {
|
||||
@Override
|
||||
public ImmutableList<String> authorizedIndicesAndAliases(User user, String action) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authorize(User user, String action, TransportRequest request) throws AuthorizationException {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,6 +46,9 @@ public interface Permission {
|
|||
|
||||
static class Global implements Permission {
|
||||
|
||||
final static Predicate<String> clusterActionMatcher = Privilege.Cluster.ALL.predicate();
|
||||
final static Predicate<String> indicesActionMatcher = Privilege.Index.ALL.predicate();
|
||||
|
||||
private final Cluster cluster;
|
||||
private final Indices indices;
|
||||
|
||||
|
@ -67,11 +70,11 @@ public interface Permission {
|
|||
}
|
||||
|
||||
public boolean check(User user, String action, TransportRequest request, MetaData metaData) {
|
||||
if (cluster != null && cluster.check(user, action, request, metaData)) {
|
||||
return true;
|
||||
if (clusterActionMatcher.apply(action)) {
|
||||
return cluster != null && cluster.check(user, action, request, metaData);
|
||||
}
|
||||
if (indices != null && indices.check(user, action, request, metaData)) {
|
||||
return true;
|
||||
if (indicesActionMatcher.apply(action)) {
|
||||
return indices != null && indices.check(user, action, request, metaData);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ public class FileRolesStore extends AbstractComponent implements RolesStore {
|
|||
|
||||
public FileRolesStore(Settings settings, Environment env, ResourceWatcherService watcherService, AuthorizationService authzService, Listener listener) {
|
||||
super(settings);
|
||||
file = resolveFile(componentSettings, env);
|
||||
file = resolveFile(settings, env);
|
||||
permissions = parseFile(file, logger, authzService);
|
||||
FileWatcher watcher = new FileWatcher(file.getParent().toFile());
|
||||
watcher.addListener(new FileListener(authzService));
|
||||
|
@ -73,7 +73,7 @@ public class FileRolesStore extends AbstractComponent implements RolesStore {
|
|||
}
|
||||
|
||||
public static Path resolveFile(Settings settings, Environment env) {
|
||||
String location = settings.get("files.roles");
|
||||
String location = settings.get("shield.authz.store.files.roles");
|
||||
if (location == null) {
|
||||
return ShieldPlugin.resolveConfigFile(env, "roles.yml");
|
||||
}
|
||||
|
|
|
@ -5,11 +5,17 @@
|
|||
*/
|
||||
package org.elasticsearch.shield.plugin;
|
||||
|
||||
import org.elasticsearch.client.support.Headers;
|
||||
import org.elasticsearch.common.collect.ImmutableList;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.plugins.AbstractPlugin;
|
||||
import org.elasticsearch.shield.ShieldModule;
|
||||
import org.elasticsearch.shield.ShieldSettingsException;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
@ -22,6 +28,12 @@ public class ShieldPlugin extends AbstractPlugin {
|
|||
|
||||
public static final String NAME = "shield";
|
||||
|
||||
private final Settings settings;
|
||||
|
||||
public ShieldPlugin(Settings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return NAME;
|
||||
|
@ -37,6 +49,26 @@ public class ShieldPlugin extends AbstractPlugin {
|
|||
return ImmutableList.<Class<? extends Module>>of(ShieldModule.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Settings additionalSettings() {
|
||||
String setting = Headers.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER;
|
||||
if (settings.get(setting) != null) {
|
||||
return ImmutableSettings.EMPTY;
|
||||
}
|
||||
String user = settings.get("shield.user");
|
||||
if (user == null) {
|
||||
return ImmutableSettings.EMPTY;
|
||||
}
|
||||
int i = user.indexOf(":");
|
||||
if (i < 0 || i == user.length() - 1) {
|
||||
throw new ShieldSettingsException("Invalid [shield.user] settings. Must be in the form of \"<username>:<password>\"");
|
||||
}
|
||||
String username = user.substring(0, i);
|
||||
String password = user.substring(i + 1);
|
||||
return ImmutableSettings.builder()
|
||||
.put(setting, UsernamePasswordToken.basicAuthHeaderValue(username, new SecuredString(password.toCharArray()))).build();
|
||||
}
|
||||
|
||||
public static Path configDir(Environment env) {
|
||||
return new File(env.configFile(), NAME).toPath();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.shield;
|
||||
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.action.search.MultiSearchResponse;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.shield.authz.AuthorizationException;
|
||||
|
@ -94,5 +95,20 @@ public class MultipleIndicesPermissionsTests extends ShieldIntegrationTest {
|
|||
} catch (AuthorizationException ae) {
|
||||
// expected
|
||||
}
|
||||
|
||||
MultiSearchResponse msearchResponse = client.prepareMultiSearch()
|
||||
.add(client.prepareSearch("test"))
|
||||
.add(client.prepareSearch("test1"))
|
||||
.get();
|
||||
MultiSearchResponse.Item[] items = msearchResponse.getResponses();
|
||||
assertThat(items.length, is(2));
|
||||
assertThat(items[0].isFailure(), is(false));
|
||||
searchResponse = items[0].getResponse();
|
||||
assertNoFailures(searchResponse);
|
||||
assertHitCount(searchResponse, 1);
|
||||
assertThat(items[1].isFailure(), is(false));
|
||||
searchResponse = items[1].getResponse();
|
||||
assertNoFailures(searchResponse);
|
||||
assertHitCount(searchResponse, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.shield;
|
||||
|
||||
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
|
||||
import org.elasticsearch.client.transport.TransportClient;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
||||
import org.elasticsearch.shield.authz.AuthorizationException;
|
||||
import org.elasticsearch.shield.test.ShieldIntegrationTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
|
||||
/**
|
||||
* This test makes sure that if an action is a cluster action (according to our
|
||||
* internal categorization in shield, then we apply the cluster priv checks and don't
|
||||
* fallback on the indices privs at all. In particular, this is useful when we want to treat
|
||||
* actions that are normally categorized as index actions as cluster actions - for example,
|
||||
* index template actions.
|
||||
*/
|
||||
public class PermissionPrecedenceTests extends ShieldIntegrationTest {
|
||||
|
||||
static final String ROLES =
|
||||
"admin:\n" +
|
||||
" cluster: all\n" +
|
||||
" indices:\n" +
|
||||
" '*': all\n" +
|
||||
"\n" +
|
||||
"user:\n" +
|
||||
" indices:\n" +
|
||||
" 'test_*': all\n";
|
||||
|
||||
static final String USERS =
|
||||
"admin:{plain}test123\n" +
|
||||
"user:{plain}test123\n";
|
||||
|
||||
static final String USERS_ROLES =
|
||||
"admin:admin\n" +
|
||||
"user:user\n";
|
||||
|
||||
@Override
|
||||
protected String configRole() {
|
||||
return ROLES;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String configUsers() {
|
||||
return USERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String configUsersRoles() {
|
||||
return USERS_ROLES;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getClientUsername() {
|
||||
return "admin";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SecuredString getClientPassword() {
|
||||
return SecuredStringTests.build("test123");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDifferetCombinationsOfIndices() throws Exception {
|
||||
|
||||
ClusterService clusterService = internalCluster().getInstance(ClusterService.class);
|
||||
TransportAddress address = clusterService.localNode().address();
|
||||
|
||||
TransportClient client = new TransportClient(ImmutableSettings.builder()
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("node.mode", "network")
|
||||
.put(getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks", "testclient")))
|
||||
.addTransportAddress(address);
|
||||
|
||||
// first lets try with "admin"... all should work
|
||||
|
||||
PutIndexTemplateResponse putResponse = client.admin().indices().preparePutTemplate("template1")
|
||||
.setTemplate("test_*")
|
||||
.putHeader("Authorization", basicAuthHeaderValue("admin", SecuredStringTests.build("test123")))
|
||||
.get();
|
||||
assertAcked(putResponse);
|
||||
|
||||
GetIndexTemplatesResponse getResponse = client.admin().indices().prepareGetTemplates("template1")
|
||||
.putHeader("Authorization", basicAuthHeaderValue("admin", SecuredStringTests.build("test123")))
|
||||
.get();
|
||||
List<IndexTemplateMetaData> templates = getResponse.getIndexTemplates();
|
||||
assertThat(templates, hasSize(1));
|
||||
|
||||
// now lets try with "user"
|
||||
|
||||
try {
|
||||
client.admin().indices().preparePutTemplate("template1")
|
||||
.setTemplate("test_*")
|
||||
.putHeader("Authorization", basicAuthHeaderValue("user", SecuredStringTests.build("test123")))
|
||||
.get();
|
||||
fail("expected an authorization exception as template APIs should require cluster ALL permission");
|
||||
} catch (AuthorizationException ae) {
|
||||
// expected;
|
||||
}
|
||||
|
||||
try {
|
||||
client.admin().indices().prepareGetTemplates("template1")
|
||||
.putHeader("Authorization", basicAuthHeaderValue("user", SecuredStringTests.build("test123")))
|
||||
.get();
|
||||
fail("expected an authorization exception as template APIs should require cluster ALL permission");
|
||||
} catch (AuthorizationException ae) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
|
@ -478,9 +478,11 @@ public class ESUsersToolTests extends CliToolTestCase {
|
|||
public void testRoles_Cmd_testNotAddingOrRemovingRolesShowsListingOfRoles() throws Exception {
|
||||
File usersFile = writeFile("admin:hash\nuser:hash");
|
||||
File usersRoleFile = writeFile("admin: admin\nuser:user\nfoo:user\nbar:user\n");
|
||||
File rolesFile = writeFile("admin:\n cluster: all\n\nuser:\n cluster: all\n\nfoo:\n cluster: all\n\nbar:\n cluster: all");
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put("shield.authc.esusers.files.users", usersFile)
|
||||
.put("shield.authc.esusers.files.users_roles", usersRoleFile)
|
||||
.put("shield.authz.store.files.roles", rolesFile)
|
||||
.build();
|
||||
|
||||
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal();
|
||||
|
@ -495,9 +497,11 @@ public class ESUsersToolTests extends CliToolTestCase {
|
|||
public void testRoles_cmd_testRoleCanBeAddedWhenUserIsNotInRolesFile() throws Exception {
|
||||
File usersFile = writeFile("admin:hash\nuser:hash");
|
||||
File usersRoleFile = writeFile("admin: admin\n");
|
||||
File rolesFile = writeFile("admin:\n cluster: all\n\nmyrole:\n cluster: all");
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put("shield.authc.esusers.files.users", usersFile)
|
||||
.put("shield.authc.esusers.files.users_roles", usersRoleFile)
|
||||
.put("shield.authz.store.files.roles", rolesFile)
|
||||
.build();
|
||||
|
||||
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal();
|
||||
|
@ -523,8 +527,10 @@ public class ESUsersToolTests extends CliToolTestCase {
|
|||
@Test
|
||||
public void testListUsersAndRoles_Cmd_listAllUsers() throws Exception {
|
||||
File usersRoleFile = writeFile("admin: admin\nuser: user\nfoo:user\nbar:user\n");
|
||||
File rolesFile = writeFile("admin:\n cluster: all\n\nuser:\n cluster: all\n\nfoo:\n cluster: all\n\nbar:\n cluster: all");
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put("shield.authc.esusers.files.users_roles", usersRoleFile)
|
||||
.put("shield.authz.store.files.roles", rolesFile)
|
||||
.build();
|
||||
|
||||
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal();
|
||||
|
@ -537,13 +543,34 @@ public class ESUsersToolTests extends CliToolTestCase {
|
|||
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(allOf(containsString("user"), containsString("user,foo,bar"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListUsersAndRoles_Cmd_listAllUsers_WithUnknownRoles() throws Exception {
|
||||
File usersRoleFile = writeFile("admin: admin\nuser: user\nfoo:user\nbar:user\n");
|
||||
File rolesFile = writeFile("admin:\n cluster: all\n\nuser:\n cluster: all");
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put("shield.authc.esusers.files.users_roles", usersRoleFile)
|
||||
.put("shield.authz.store.files.roles", rolesFile)
|
||||
.build();
|
||||
|
||||
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal();
|
||||
ESUsersTool.ListUsersAndRoles cmd = new ESUsersTool.ListUsersAndRoles(catchTerminalOutput, null);
|
||||
CliTool.ExitStatus status = execute(cmd, settings);
|
||||
|
||||
assertThat(status, is(CliTool.ExitStatus.OK));
|
||||
assertThat(catchTerminalOutput.getTerminalOutput(), hasSize(greaterThanOrEqualTo(2)));
|
||||
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(containsString("admin")));
|
||||
assertThat(catchTerminalOutput.getTerminalOutput(), hasItem(allOf(containsString("user"), containsString("user,foo*,bar*"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListUsersAndRoles_Cmd_listSingleUser() throws Exception {
|
||||
File usersRoleFile = writeFile("admin: admin\nuser: user\nfoo:user\nbar:user\n");
|
||||
File usersFile = writeFile("admin:{plain}changeme\nuser:{plain}changeme\nno-roles-user:{plain}changeme\n");
|
||||
File rolesFile = writeFile("admin:\n cluster: all\n\nuser:\n cluster: all\n\nfoo:\n cluster: all");
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put("shield.authc.esusers.files.users_roles", usersRoleFile)
|
||||
.put("shield.authc.esusers.files.users", usersFile)
|
||||
.put("shield.authz.store.files.roles", rolesFile)
|
||||
.build();
|
||||
|
||||
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal();
|
||||
|
@ -574,9 +601,11 @@ public class ESUsersToolTests extends CliToolTestCase {
|
|||
public void testListUsersAndRoles_Cmd_testThatUsersWithoutRolesAreListed() throws Exception {
|
||||
File usersFile = writeFile("admin:{plain}changeme\nuser:{plain}changeme\nno-roles-user:{plain}changeme\n");
|
||||
File usersRoleFile = writeFile("admin: admin\nuser: user\nfoo:user\nbar:user\n");
|
||||
File rolesFile = writeFile("admin:\n cluster: all\n\nuser:\n cluster: all\n\nfoo:\n cluster: all\n\nbar:\n cluster: all");
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put("shield.authc.esusers.files.users_roles", usersRoleFile)
|
||||
.put("shield.authc.esusers.files.users", usersFile)
|
||||
.put("shield.authz.store.files.roles", rolesFile)
|
||||
.build();
|
||||
|
||||
CaptureOutputTerminal catchTerminalOutput = new CaptureOutputTerminal();
|
||||
|
|
|
@ -63,19 +63,20 @@ public abstract class ShieldIntegrationTest extends ElasticsearchIntegrationTest
|
|||
File folder = newFolder();
|
||||
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder()
|
||||
.put("request.headers.Authorization", basicAuthHeaderValue(getClientUsername(), getClientPassword()))
|
||||
.put("discovery.zen.ping.multicast.enabled", false)
|
||||
.put("discovery.type", "zen")
|
||||
.put("node.mode", "network")
|
||||
.put("plugin.types", ShieldPlugin.class.getName())
|
||||
.put("shield.authc.esusers.files.users", writeFile(folder, "users", CONFIG_STANDARD_USER))
|
||||
.put("shield.authc.esusers.files.users_roles", writeFile(folder, "users_roles", CONFIG_STANDARD_USER_ROLES))
|
||||
.put("shield.authc.esusers.files.users", writeFile(folder, "users", configUsers()))
|
||||
.put("shield.authc.esusers.files.users_roles", writeFile(folder, "users_roles", configUsersRoles()))
|
||||
.put("shield.authz.store.files.roles", writeFile(folder, "roles.yml", configRole()))
|
||||
.put("shield.transport.n2n.ip_filter.file", writeFile(folder, "ip_filter.yml", CONFIG_IPFILTER_ALLOW_ALL))
|
||||
.put(getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks", "testnode"))
|
||||
.put("shield.audit.enabled", true)
|
||||
.put("plugins.load_classpath_plugins", false);
|
||||
|
||||
setUser(builder);
|
||||
|
||||
if (OsUtils.MAC) {
|
||||
builder.put("network.host", randomBoolean() ? "127.0.0.1" : "::1");
|
||||
}
|
||||
|
@ -87,15 +88,34 @@ public abstract class ShieldIntegrationTest extends ElasticsearchIntegrationTest
|
|||
return CONFIG_ROLE_ALLOW_ALL;
|
||||
}
|
||||
|
||||
protected String configUsers() {
|
||||
return CONFIG_STANDARD_USER;
|
||||
}
|
||||
|
||||
protected String configUsersRoles() {
|
||||
return CONFIG_STANDARD_USER_ROLES;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Settings transportClientSettings() {
|
||||
return ImmutableSettings.builder()
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder()
|
||||
.put("request.headers.Authorization", basicAuthHeaderValue(getClientUsername(), getClientPassword()))
|
||||
.put(TransportModule.TRANSPORT_TYPE_KEY, NettySecuredTransport.class.getName())
|
||||
.put("plugins." + PluginsService.LOAD_PLUGIN_FROM_CLASSPATH, false)
|
||||
.put("node.mode", "network")
|
||||
.put(getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks", "testclient"))
|
||||
.build();
|
||||
.put(getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks", "testclient"));
|
||||
|
||||
setUser(builder);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected void setUser(ImmutableSettings.Builder settings) {
|
||||
if (randomBoolean()) {
|
||||
settings.put("request.headers.Authorization", basicAuthHeaderValue(getClientUsername(), getClientPassword()));
|
||||
} else {
|
||||
settings.put("shield.user", getClientUsername() + ":" + new String(getClientPassword().internalChars()));
|
||||
}
|
||||
}
|
||||
|
||||
protected String writeFile(File folder, String name, String content) {
|
||||
|
|
Loading…
Reference in New Issue