Merge pull request elastic/elasticsearch#1374 from jaymode/request_context
replace ContextAndHeaders with ThreadContext Original commit: elastic/x-pack-elasticsearch@469ab3f5a1
This commit is contained in:
commit
d587ace5f1
|
@ -95,9 +95,9 @@ public class ShieldCachePermissionTests extends ShieldIntegTestCase {
|
|||
|
||||
// Repeat with unauthorized user!!!!
|
||||
try {
|
||||
response = client().prepareSearch("data").setTypes("a").setQuery(QueryBuilders.constantScoreQuery(
|
||||
response = client().filterWithHeader(Collections.singletonMap("Authorization", basicAuthHeaderValue(READ_ONE_IDX_USER, new SecuredString("changeme".toCharArray()))))
|
||||
.prepareSearch("data").setTypes("a").setQuery(QueryBuilders.constantScoreQuery(
|
||||
QueryBuilders.termsLookupQuery("token", new TermsLookup("tokens", "tokens", "1", "tokens"))))
|
||||
.putHeader("Authorization", basicAuthHeaderValue(READ_ONE_IDX_USER, new SecuredString("changeme".toCharArray())))
|
||||
.execute().actionGet();
|
||||
fail("search phase exception should have been thrown! response was:\n" + response.toString());
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
|
@ -115,9 +115,9 @@ public class ShieldCachePermissionTests extends ShieldIntegTestCase {
|
|||
|
||||
// Repeat with unauthorized user!!!!
|
||||
try {
|
||||
response = client().prepareSearch("data").setTypes("a")
|
||||
response = client().filterWithHeader(Collections.singletonMap("Authorization", basicAuthHeaderValue(READ_ONE_IDX_USER, new SecuredString("changeme".toCharArray()))))
|
||||
.prepareSearch("data").setTypes("a")
|
||||
.setTemplate(new Template("testTemplate", ScriptService.ScriptType.INDEXED, MustacheScriptEngineService.NAME, null, Collections.<String, Object>singletonMap("name", "token")))
|
||||
.putHeader("Authorization", basicAuthHeaderValue(READ_ONE_IDX_USER, new SecuredString("changeme".toCharArray())))
|
||||
.execute().actionGet();
|
||||
fail("search phase exception should have been thrown! response was:\n" + response.toString());
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
|
|
|
@ -90,7 +90,8 @@ public class ShieldTransportClientIT extends ESIntegTestCase {
|
|||
// this checks that the transport client is really running in a limited state
|
||||
ClusterHealthResponse response;
|
||||
if (useTransportUser) {
|
||||
response = client.admin().cluster().prepareHealth().putHeader("Authorization", basicAuthHeaderValue("test_user", new SecuredString("changeme".toCharArray()))).get();
|
||||
response = client.filterWithHeader(Collections.singletonMap("Authorization", basicAuthHeaderValue("test_user", new SecuredString("changeme".toCharArray()))))
|
||||
.admin().cluster().prepareHealth().get();
|
||||
} else {
|
||||
response = client.admin().cluster().prepareHealth().get();
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ package org.elasticsearch.shield;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.elasticsearch.client.support.Headers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
|
@ -36,7 +36,7 @@ public class RestIT extends ESRestTestCase {
|
|||
protected Settings restClientSettings() {
|
||||
String token = basicAuthHeaderValue(USER, new SecuredString(PASS.toCharArray()));
|
||||
return Settings.builder()
|
||||
.put(Headers.PREFIX + ".Authorization", token)
|
||||
.put(ThreadContext.PREFIX + ".Authorization", token)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
*/
|
||||
package org.elasticsearch.example.realm;
|
||||
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.authc.AuthenticationToken;
|
||||
import org.elasticsearch.shield.authc.Realm;
|
||||
import org.elasticsearch.shield.authc.RealmConfig;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
|
||||
public class CustomRealm extends Realm<UsernamePasswordToken> {
|
||||
|
||||
|
@ -35,22 +34,10 @@ public class CustomRealm extends Realm<UsernamePasswordToken> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public UsernamePasswordToken token(RestRequest request) {
|
||||
String user = request.header(USER_HEADER);
|
||||
public UsernamePasswordToken token(ThreadContext threadContext) {
|
||||
String user = threadContext.getHeader(USER_HEADER);
|
||||
if (user != null) {
|
||||
String password = request.header(PW_HEADER);
|
||||
if (password != null) {
|
||||
return new UsernamePasswordToken(user, new SecuredString(password.toCharArray()));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UsernamePasswordToken token(TransportMessage<?> message) {
|
||||
String user = message.getHeader(USER_HEADER);
|
||||
if (user != null) {
|
||||
String password = message.getHeader(PW_HEADER);
|
||||
String password = threadContext.getHeader(PW_HEADER);
|
||||
if (password != null) {
|
||||
return new UsernamePasswordToken(user, new SecuredString(password.toCharArray()));
|
||||
}
|
||||
|
|
|
@ -5,13 +5,17 @@
|
|||
*/
|
||||
package org.elasticsearch.example.realm;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.shield.authc.Realm;
|
||||
import org.elasticsearch.shield.authc.RealmConfig;
|
||||
|
||||
public class CustomRealmFactory extends Realm.Factory<CustomRealm> {
|
||||
|
||||
public CustomRealmFactory() {
|
||||
@Inject
|
||||
public CustomRealmFactory(RestController controller) {
|
||||
super(CustomRealm.TYPE, false);
|
||||
controller.registerRelevantHeaders(CustomRealm.USER_HEADER, CustomRealm.PW_HEADER);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,11 +8,11 @@ package org.elasticsearch.example.realm;
|
|||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||
import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
|
||||
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
|
||||
import org.elasticsearch.client.support.Headers;
|
||||
import org.elasticsearch.client.transport.NoNodeAvailableException;
|
||||
import org.elasticsearch.client.transport.TransportClient;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.rest.client.http.HttpResponse;
|
||||
|
@ -30,8 +30,8 @@ public class CustomRealmIT extends ESIntegTestCase {
|
|||
@Override
|
||||
protected Settings externalClusterClientSettings() {
|
||||
return Settings.builder()
|
||||
.put(Headers.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
||||
.put(Headers.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,8 @@ public class CustomRealmIT extends ESIntegTestCase {
|
|||
|
||||
Settings settings = Settings.builder()
|
||||
.put("cluster.name", clusterName)
|
||||
.put(Headers.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
||||
.put(Headers.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.build();
|
||||
try (TransportClient client = TransportClient.builder().settings(settings).addPlugin(XPackPlugin.class).build()) {
|
||||
client.addTransportAddress(publishAddress);
|
||||
|
@ -83,8 +83,8 @@ public class CustomRealmIT extends ESIntegTestCase {
|
|||
|
||||
Settings settings = Settings.builder()
|
||||
.put("cluster.name", clusterName)
|
||||
.put(Headers.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER + randomAsciiOfLength(1))
|
||||
.put(Headers.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER + randomAsciiOfLength(1))
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.build();
|
||||
try (TransportClient client = TransportClient.builder().addPlugin(XPackPlugin.class).settings(settings).build()) {
|
||||
client.addTransportAddress(publishAddress);
|
||||
|
|
|
@ -8,9 +8,9 @@ package org.elasticsearch.smoketest;
|
|||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.client.support.Headers;
|
||||
import org.elasticsearch.common.io.PathUtils;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
|
@ -64,7 +64,7 @@ public class SmokeTestPluginsSslIT extends ESRestTestCase {
|
|||
protected Settings restClientSettings() {
|
||||
String token = basicAuthHeaderValue(USER, new SecuredString(PASS.toCharArray()));
|
||||
return Settings.builder()
|
||||
.put(Headers.PREFIX + ".Authorization", token)
|
||||
.put(ThreadContext.PREFIX + ".Authorization", token)
|
||||
.put(RestClient.PROTOCOL, "https")
|
||||
.put(RestClient.TRUSTSTORE_PATH, keyStore)
|
||||
.put(RestClient.TRUSTSTORE_PASSWORD, KEYSTORE_PASS)
|
||||
|
|
|
@ -7,8 +7,8 @@ package org.elasticsearch.smoketest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.elasticsearch.client.support.Headers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
|
@ -36,7 +36,7 @@ public class SmokeTestPluginsIT extends ESRestTestCase {
|
|||
protected Settings restClientSettings() {
|
||||
String token = basicAuthHeaderValue(USER, new SecuredString(PASS.toCharArray()));
|
||||
return Settings.builder()
|
||||
.put(Headers.PREFIX + ".Authorization", token)
|
||||
.put(ThreadContext.PREFIX + ".Authorization", token)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ import org.apache.http.client.methods.HttpPut;
|
|||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
||||
import org.elasticsearch.client.support.Headers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
|
@ -67,7 +67,7 @@ public class WatcherWithShieldIT extends ESRestTestCase {
|
|||
protected Settings restClientSettings() {
|
||||
String token = basicAuthHeaderValue("watcher_manager", new SecuredString("changeme".toCharArray()));
|
||||
return Settings.builder()
|
||||
.put(Headers.PREFIX + ".Authorization", token)
|
||||
.put(ThreadContext.PREFIX + ".Authorization", token)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ public class WatcherWithShieldIT extends ESRestTestCase {
|
|||
protected Settings restAdminSettings() {
|
||||
String token = basicAuthHeaderValue(TEST_ADMIN_USERNAME, new SecuredString(TEST_ADMIN_PASSWORD.toCharArray()));
|
||||
return Settings.builder()
|
||||
.put(Headers.PREFIX + ".Authorization", token)
|
||||
.put(ThreadContext.PREFIX + ".Authorization", token)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ public class RestDeleteLicenseAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestDeleteLicenseAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
controller.registerHandler(DELETE, "/_license", this);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ public class RestGetLicenseAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestGetLicenseAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
controller.registerHandler(GET, "/_license", this);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ public class RestPutLicenseAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestPutLicenseAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
controller.registerHandler(PUT, "/_license", this);
|
||||
controller.registerHandler(POST, "/_license", this);
|
||||
}
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
package org.elasticsearch.marvel.shield;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.shield.ShieldPlugin;
|
||||
import org.elasticsearch.shield.ShieldSettingsFilter;
|
||||
import org.elasticsearch.shield.authc.AuthenticationService;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -24,18 +24,24 @@ public class MarvelShieldIntegration {
|
|||
private final boolean enabled;
|
||||
private final AuthenticationService authcService;
|
||||
private final ShieldSettingsFilter settingsFilter;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
public MarvelShieldIntegration(Settings settings, Injector injector) {
|
||||
enabled = enabled(settings);
|
||||
authcService = enabled ? injector.getInstance(AuthenticationService.class) : null;
|
||||
settingsFilter = enabled ? injector.getInstance(ShieldSettingsFilter.class) : null;
|
||||
client = injector.getInstance(Client.class);
|
||||
}
|
||||
|
||||
public void bindInternalMarvelUser(TransportMessage message) {
|
||||
public Client getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void bindInternalMarvelUser() {
|
||||
if (authcService != null) {
|
||||
try {
|
||||
authcService.attachUserHeaderIfMissing(message, InternalMarvelUser.INSTANCE);
|
||||
authcService.attachUserHeaderIfMissing(InternalMarvelUser.INSTANCE);
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("failed to attach marvel user to request", e);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.elasticsearch.action.ActionResponse;
|
|||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.FilterClient;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -29,8 +30,10 @@ public class SecuredClient extends FilterClient {
|
|||
|
||||
@Override
|
||||
protected <Request extends ActionRequest<Request>, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void doExecute(
|
||||
Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) {
|
||||
this.shieldIntegration.bindInternalMarvelUser(request);
|
||||
super.doExecute(action, request, listener);
|
||||
Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) {
|
||||
try (ThreadContext.StoredContext ctx = threadPool().getThreadContext().stashContext()) {
|
||||
this.shieldIntegration.bindInternalMarvelUser();
|
||||
super.doExecute(action, request, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,12 +66,14 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase {
|
|||
|
||||
public SecuredClient securedClient() {
|
||||
MarvelShieldIntegration integration = internalCluster().getInstance(MarvelShieldIntegration.class);
|
||||
return new SecuredClient(client(), integration);
|
||||
// we must get the client from the same node!
|
||||
return new SecuredClient(integration.getClient(), integration);
|
||||
}
|
||||
|
||||
public SecuredClient securedClient(String nodeId) {
|
||||
MarvelShieldIntegration integration = internalCluster().getInstance(MarvelShieldIntegration.class);
|
||||
return new SecuredClient(client(nodeId), integration);
|
||||
MarvelShieldIntegration integration = internalCluster().getInstance(MarvelShieldIntegration.class, nodeId);
|
||||
// we must get the client from the same node!
|
||||
return new SecuredClient(integration.getClient(), integration);
|
||||
}
|
||||
|
||||
protected void assertCanCollect(AbstractCollector collector) {
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
package org.elasticsearch.marvel.test;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
|
@ -44,7 +46,9 @@ import java.util.HashSet;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
|
@ -116,6 +120,16 @@ public abstract class MarvelIntegTestCase extends ESIntegTestCase {
|
|||
return nodePlugins();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<Client,Client> getClientWrapper() {
|
||||
if (shieldEnabled == false) {
|
||||
return Function.identity();
|
||||
}
|
||||
Map<String, String> headers = Collections.singletonMap("Authorization",
|
||||
basicAuthHeaderValue(ShieldSettings.TEST_USERNAME, new SecuredString(ShieldSettings.TEST_PASSWORD.toCharArray())));
|
||||
return client -> (client instanceof NodeClient) ? client.filterWithHeader(headers) : client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override and returns {@code false} to force running without shield
|
||||
*/
|
||||
|
@ -386,7 +400,6 @@ public abstract class MarvelIntegTestCase extends ESIntegTestCase {
|
|||
builder.remove("index.queries.cache.type");
|
||||
|
||||
builder.put("shield.enabled", true)
|
||||
.put("shield.user", "test:changeme")
|
||||
.put("shield.authc.realms.esusers.type", ESUsersRealm.TYPE)
|
||||
.put("shield.authc.realms.esusers.order", 0)
|
||||
.put("shield.authc.realms.esusers.files.users", writeFile(folder, "users", USERS))
|
||||
|
|
|
@ -7,12 +7,12 @@ package org.elasticsearch.shield;
|
|||
|
||||
import org.elasticsearch.action.ActionModule;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.support.Headers;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsModule;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.index.IndexModule;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
|
@ -194,7 +194,8 @@ public class ShieldPlugin extends Plugin {
|
|||
if (flsDlsEnabled(settings)) {
|
||||
module.setSearcherWrapper((indexService) -> new ShieldIndexSearcherWrapper(indexService.getIndexSettings(),
|
||||
indexService.getQueryShardContext(), indexService.mapperService(),
|
||||
indexService.cache().bitsetFilterCache(), shieldLicenseState));
|
||||
indexService.cache().bitsetFilterCache(), indexService.getIndexServices().getThreadPool().getThreadContext(),
|
||||
shieldLicenseState));
|
||||
}
|
||||
if (clientMode == false) {
|
||||
module.registerQueryCache(ShieldPlugin.OPT_OUT_QUERY_CACHE, OptOutQueryCache::new);
|
||||
|
@ -263,7 +264,7 @@ public class ShieldPlugin extends Plugin {
|
|||
}
|
||||
|
||||
private void addUserSettings(Settings.Builder settingsBuilder) {
|
||||
String authHeaderSettingName = Headers.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER;
|
||||
String authHeaderSettingName = ThreadContext.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER;
|
||||
if (settings.get(authHeaderSettingName) != null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.action.support.ActionFilterChain;
|
|||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.license.plugin.core.LicenseUtils;
|
||||
import org.elasticsearch.shield.ShieldPlugin;
|
||||
import org.elasticsearch.shield.User;
|
||||
|
@ -26,7 +27,10 @@ import org.elasticsearch.shield.authz.AuthorizationService;
|
|||
import org.elasticsearch.shield.authz.privilege.HealthAndStatsPrivilege;
|
||||
import org.elasticsearch.shield.crypto.CryptoService;
|
||||
import org.elasticsearch.shield.license.ShieldLicenseState;
|
||||
import org.elasticsearch.shield.support.AutomatonPredicate;
|
||||
import org.elasticsearch.shield.support.Automatons;
|
||||
import org.elasticsearch.tasks.Task;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -42,6 +46,8 @@ import static org.elasticsearch.shield.support.Exceptions.authorizationError;
|
|||
public class ShieldActionFilter extends AbstractComponent implements ActionFilter {
|
||||
|
||||
private static final Predicate<String> LICENSE_EXPIRATION_ACTION_MATCHER = HealthAndStatsPrivilege.INSTANCE.predicate();
|
||||
// FIXME clean up this hack
|
||||
static final Predicate<String> INTERNAL_PREDICATE = new AutomatonPredicate(Automatons.patterns("internal:*"));
|
||||
|
||||
private final AuthenticationService authcService;
|
||||
private final AuthorizationService authzService;
|
||||
|
@ -50,10 +56,12 @@ public class ShieldActionFilter extends AbstractComponent implements ActionFilte
|
|||
private final ShieldActionMapper actionMapper;
|
||||
private final Set<RequestInterceptor> requestInterceptors;
|
||||
private final ShieldLicenseState licenseState;
|
||||
private final ThreadContext threadContext;
|
||||
|
||||
@Inject
|
||||
public ShieldActionFilter(Settings settings, AuthenticationService authcService, AuthorizationService authzService, CryptoService cryptoService,
|
||||
AuditTrail auditTrail, ShieldLicenseState licenseState, ShieldActionMapper actionMapper, Set<RequestInterceptor> requestInterceptors) {
|
||||
AuditTrail auditTrail, ShieldLicenseState licenseState, ShieldActionMapper actionMapper, Set<RequestInterceptor> requestInterceptors,
|
||||
ThreadPool threadPool) {
|
||||
super(settings);
|
||||
this.authcService = authcService;
|
||||
this.authzService = authzService;
|
||||
|
@ -62,6 +70,7 @@ public class ShieldActionFilter extends AbstractComponent implements ActionFilte
|
|||
this.actionMapper = actionMapper;
|
||||
this.licenseState = licenseState;
|
||||
this.requestInterceptors = requestInterceptors;
|
||||
this.threadContext = threadPool.getThreadContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,8 +87,56 @@ public class ShieldActionFilter extends AbstractComponent implements ActionFilte
|
|||
throw LicenseUtils.newComplianceException(ShieldPlugin.NAME);
|
||||
}
|
||||
|
||||
try {
|
||||
try (ThreadContext.StoredContext original = threadContext.newStoredContext()) {
|
||||
if (licenseState.securityEnabled()) {
|
||||
// FIXME yet another hack. Needed to work around something like
|
||||
/*
|
||||
FailedNodeException[total failure in fetching]; nested: ElasticsearchSecurityException[action [internal:gateway/local/started_shards] is unauthorized for user [test_user]];
|
||||
at org.elasticsearch.gateway.AsyncShardFetch$1.onFailure(AsyncShardFetch.java:284)
|
||||
at org.elasticsearch.action.support.TransportAction$1.onFailure(TransportAction.java:84)
|
||||
at org.elasticsearch.shield.action.ShieldActionFilter.apply(ShieldActionFilter.java:121)
|
||||
at org.elasticsearch.action.support.TransportAction$RequestFilterChain.proceed(TransportAction.java:133)
|
||||
at org.elasticsearch.action.support.TransportAction.execute(TransportAction.java:107)
|
||||
at org.elasticsearch.action.support.TransportAction.execute(TransportAction.java:74)
|
||||
at org.elasticsearch.gateway.TransportNodesListGatewayStartedShards.list(TransportNodesListGatewayStartedShards.java:78)
|
||||
at org.elasticsearch.gateway.AsyncShardFetch.asyncFetch(AsyncShardFetch.java:274)
|
||||
at org.elasticsearch.gateway.AsyncShardFetch.fetchData(AsyncShardFetch.java:124)
|
||||
at org.elasticsearch.gateway.GatewayAllocator$InternalPrimaryShardAllocator.fetchData(GatewayAllocator.java:156)
|
||||
at org.elasticsearch.gateway.PrimaryShardAllocator.allocateUnassigned(PrimaryShardAllocator.java:83)
|
||||
at org.elasticsearch.gateway.GatewayAllocator.allocateUnassigned(GatewayAllocator.java:120)
|
||||
at org.elasticsearch.cluster.routing.allocation.allocator.ShardsAllocators.allocateUnassigned(ShardsAllocators.java:72)
|
||||
at org.elasticsearch.cluster.routing.allocation.AllocationService.reroute(AllocationService.java:309)
|
||||
at org.elasticsearch.cluster.routing.allocation.AllocationService.reroute(AllocationService.java:273)
|
||||
at org.elasticsearch.cluster.routing.allocation.AllocationService.reroute(AllocationService.java:259)
|
||||
at org.elasticsearch.cluster.routing.RoutingService$2.execute(RoutingService.java:158)
|
||||
at org.elasticsearch.cluster.ClusterStateUpdateTask.execute(ClusterStateUpdateTask.java:45)
|
||||
at org.elasticsearch.cluster.service.InternalClusterService.runTasksForExecutor(InternalClusterService.java:447)
|
||||
at org.elasticsearch.cluster.service.InternalClusterService$UpdateTask.run(InternalClusterService.java:757)
|
||||
at org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor$FilterRunnable.run(EsThreadPoolExecutor.java:211)
|
||||
at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.runAndClean(PrioritizedEsThreadPoolExecutor.java:237)
|
||||
at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.run(PrioritizedEsThreadPoolExecutor.java:200)
|
||||
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
|
||||
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
|
||||
at java.lang.Thread.run(Thread.java:745)
|
||||
*/
|
||||
if (INTERNAL_PREDICATE.test(action)) {
|
||||
try (ThreadContext.StoredContext ctx = threadContext.stashContext()) {
|
||||
String shieldAction = actionMapper.action(action, request);
|
||||
User user = authcService.authenticate(shieldAction, request, User.SYSTEM);
|
||||
authzService.authorize(user, shieldAction, request);
|
||||
request = unsign(user, shieldAction, request);
|
||||
|
||||
for (RequestInterceptor interceptor : requestInterceptors) {
|
||||
if (interceptor.supports(request)) {
|
||||
interceptor.intercept(request, user);
|
||||
}
|
||||
}
|
||||
chain.proceed(task, action, request, new SigningListener(this, listener));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
here we fallback on the system user. Internal system requests are requests that are triggered by
|
||||
the system itself (e.g. pings, update mappings, share relocation, etc...) and were not originated
|
||||
|
|
|
@ -27,7 +27,7 @@ public class RestAddRoleAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestAddRoleAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
controller.registerHandler(RestRequest.Method.POST, "/_shield/role/{role}", this);
|
||||
controller.registerHandler(RestRequest.Method.PUT, "/_shield/role/{role}", this);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ public class RestDeleteRoleAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestDeleteRoleAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
controller.registerHandler(RestRequest.Method.DELETE, "/_shield/role/{role}", this);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ public class RestGetRolesAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestGetRolesAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
controller.registerHandler(RestRequest.Method.GET, "/_shield/role/", this);
|
||||
controller.registerHandler(RestRequest.Method.GET, "/_shield/role/{roles}", this);
|
||||
controller.registerHandler(RestRequest.Method.GET, "/_shield/roles/", this);
|
||||
|
|
|
@ -30,7 +30,7 @@ public class RestAddUserAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestAddUserAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
controller.registerHandler(RestRequest.Method.POST, "/_shield/user/{username}", this);
|
||||
controller.registerHandler(RestRequest.Method.PUT, "/_shield/user/{username}", this);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public class RestDeleteUserAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestDeleteUserAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
controller.registerHandler(RestRequest.Method.DELETE, "/_shield/user/{username}", this);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ public class RestGetUsersAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestGetUsersAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
controller.registerHandler(RestRequest.Method.GET, "/_shield/user/", this);
|
||||
controller.registerHandler(RestRequest.Method.GET, "/_shield/user/{user}", this);
|
||||
controller.registerHandler(RestRequest.Method.GET, "/_shield/users/", this);
|
||||
|
|
|
@ -93,7 +93,7 @@ public class ClearRealmCacheRequest extends BaseNodesRequest<ClearRealmCacheRequ
|
|||
}
|
||||
|
||||
Node(ClearRealmCacheRequest request, String nodeId) {
|
||||
super(request, nodeId);
|
||||
super(nodeId);
|
||||
this.realms = request.realms;
|
||||
this.usernames = request.usernames;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public class ClearRolesCacheRequest extends BaseNodesRequest<ClearRolesCacheRequ
|
|||
}
|
||||
|
||||
public Node(ClearRolesCacheRequest request, String nodeId) {
|
||||
super(request, nodeId);
|
||||
super(nodeId);
|
||||
this.roles = request.roles();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,12 @@ import org.elasticsearch.action.update.UpdateRequest;
|
|||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.authz.InternalAuthorizationService;
|
||||
import org.elasticsearch.shield.authz.accesscontrol.IndicesAccessControl;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
|
||||
/**
|
||||
|
@ -23,13 +25,16 @@ import org.elasticsearch.transport.TransportRequest;
|
|||
*/
|
||||
public class BulkRequestInterceptor extends AbstractComponent implements RequestInterceptor<BulkRequest> {
|
||||
|
||||
private final ThreadContext threadContext;
|
||||
|
||||
@Inject
|
||||
public BulkRequestInterceptor(Settings settings) {
|
||||
public BulkRequestInterceptor(Settings settings, ThreadPool threadPool) {
|
||||
super(settings);
|
||||
this.threadContext = threadPool.getThreadContext();
|
||||
}
|
||||
|
||||
public void intercept(BulkRequest request, User user) {
|
||||
IndicesAccessControl indicesAccessControl = ((TransportRequest) request).getFromContext(InternalAuthorizationService.INDICES_PERMISSIONS_KEY);
|
||||
IndicesAccessControl indicesAccessControl= threadContext.getTransient(InternalAuthorizationService.INDICES_PERMISSIONS_KEY);
|
||||
for (IndicesRequest indicesRequest : request.subRequests()) {
|
||||
for (String index : indicesRequest.indices()) {
|
||||
IndicesAccessControl.IndexAccessControl indexAccessControl = indicesAccessControl.getIndexPermissions(index);
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.elasticsearch.action.IndicesRequest;
|
|||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.authz.InternalAuthorizationService;
|
||||
import org.elasticsearch.shield.authz.accesscontrol.IndicesAccessControl;
|
||||
|
@ -24,8 +25,11 @@ import java.util.List;
|
|||
*/
|
||||
public abstract class FieldAndDocumentLevelSecurityRequestInterceptor<Request> extends AbstractComponent implements RequestInterceptor<Request> {
|
||||
|
||||
public FieldAndDocumentLevelSecurityRequestInterceptor(Settings settings) {
|
||||
private final ThreadContext threadContext;
|
||||
|
||||
public FieldAndDocumentLevelSecurityRequestInterceptor(Settings settings, ThreadContext threadContext) {
|
||||
super(settings);
|
||||
this.threadContext = threadContext;
|
||||
}
|
||||
|
||||
public void intercept(Request request, User user) {
|
||||
|
@ -37,7 +41,7 @@ public abstract class FieldAndDocumentLevelSecurityRequestInterceptor<Request> e
|
|||
} else {
|
||||
throw new IllegalArgumentException(LoggerMessageFormat.format("Expected a request of type [{}] or [{}] but got [{}] instead", CompositeIndicesRequest.class, IndicesRequest.class, request.getClass()));
|
||||
}
|
||||
IndicesAccessControl indicesAccessControl = ((TransportRequest) request).getFromContext(InternalAuthorizationService.INDICES_PERMISSIONS_KEY);
|
||||
IndicesAccessControl indicesAccessControl = threadContext.getTransient(InternalAuthorizationService.INDICES_PERMISSIONS_KEY);
|
||||
for (IndicesRequest indicesRequest : indicesRequests) {
|
||||
for (String index : indicesRequest.indices()) {
|
||||
IndicesAccessControl.IndexAccessControl indexAccessControl = indicesAccessControl.getIndexPermissions(index);
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.shield.action.interceptor;
|
|||
import org.elasticsearch.action.RealtimeRequest;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
|
||||
/**
|
||||
|
@ -17,8 +18,8 @@ import org.elasticsearch.transport.TransportRequest;
|
|||
public class RealtimeRequestInterceptor extends FieldAndDocumentLevelSecurityRequestInterceptor<RealtimeRequest> {
|
||||
|
||||
@Inject
|
||||
public RealtimeRequestInterceptor(Settings settings) {
|
||||
super(settings);
|
||||
public RealtimeRequestInterceptor(Settings settings, ThreadPool threadPool) {
|
||||
super(settings, threadPool.getThreadContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.shield.action.interceptor;
|
|||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
|
||||
/**
|
||||
|
@ -16,8 +17,8 @@ import org.elasticsearch.transport.TransportRequest;
|
|||
public class SearchRequestInterceptor extends FieldAndDocumentLevelSecurityRequestInterceptor<SearchRequest> {
|
||||
|
||||
@Inject
|
||||
public SearchRequestInterceptor(Settings settings) {
|
||||
super(settings);
|
||||
public SearchRequestInterceptor(Settings settings, ThreadPool threadPool) {
|
||||
super(settings, threadPool.getThreadContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.elasticsearch.action.update.UpdateRequest;
|
|||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
|
||||
/**
|
||||
|
@ -22,8 +23,8 @@ import org.elasticsearch.transport.TransportRequest;
|
|||
public class UpdateRequestInterceptor extends FieldAndDocumentLevelSecurityRequestInterceptor<UpdateRequest> {
|
||||
|
||||
@Inject
|
||||
public UpdateRequestInterceptor(Settings settings) {
|
||||
super(settings);
|
||||
public UpdateRequestInterceptor(Settings settings, ThreadPool threadPool) {
|
||||
super(settings, threadPool.getThreadContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
|
||||
import org.elasticsearch.gateway.GatewayService;
|
||||
import org.elasticsearch.shield.authc.AuthenticationService;
|
||||
import org.elasticsearch.shield.support.ClientWithUser;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -58,8 +59,7 @@ public class ShieldTemplateService extends AbstractComponent implements ClusterS
|
|||
}
|
||||
|
||||
private void createShieldTemplate() {
|
||||
Client client = this.clientProvider.get();
|
||||
AuthenticationService authService = this.authProvider.get();
|
||||
final Client client = getClient();
|
||||
try (InputStream is = getClass().getResourceAsStream("/" + SHIELD_TEMPLATE_NAME + ".json")) {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
Streams.copy(is, out);
|
||||
|
@ -67,7 +67,6 @@ public class ShieldTemplateService extends AbstractComponent implements ClusterS
|
|||
logger.info("--> putting the shield index template");
|
||||
PutIndexTemplateRequest putTemplateRequest = client.admin().indices()
|
||||
.preparePutTemplate(SHIELD_TEMPLATE_NAME).setSource(template).request();
|
||||
authService.attachUserHeaderIfMissing(putTemplateRequest, adminUser.user());
|
||||
PutIndexTemplateResponse templateResponse = client.admin().indices().putTemplate(putTemplateRequest).get();
|
||||
if (templateResponse.isAcknowledged() == false) {
|
||||
throw new ElasticsearchException("adding template for shield admin index was not acknowledged");
|
||||
|
@ -81,6 +80,10 @@ public class ShieldTemplateService extends AbstractComponent implements ClusterS
|
|||
|
||||
}
|
||||
|
||||
Client getClient() {
|
||||
return new ClientWithUser(clientProvider.get(), authProvider.get(), adminUser.user());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clusterChanged(ClusterChangedEvent event) {
|
||||
if (event.state().blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) {
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.elasticsearch.common.transport.TransportAddress;
|
|||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
|
||||
import org.elasticsearch.common.util.concurrent.EsExecutors;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilderString;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
|
@ -44,12 +45,12 @@ import org.elasticsearch.gateway.GatewayService;
|
|||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.shield.admin.ShieldInternalUserHolder;
|
||||
import org.elasticsearch.shield.authz.privilege.SystemPrivilege;
|
||||
import org.elasticsearch.shield.support.ClientWithUser;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.audit.AuditTrail;
|
||||
import org.elasticsearch.shield.authc.AuthenticationService;
|
||||
import org.elasticsearch.shield.authc.AuthenticationToken;
|
||||
import org.elasticsearch.shield.authz.privilege.Privilege;
|
||||
import org.elasticsearch.shield.rest.RemoteHostHeader;
|
||||
import org.elasticsearch.shield.transport.filter.ShieldIpFilterRule;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
@ -525,7 +526,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
|||
|
||||
Message msg = new Message().start();
|
||||
common("transport", type, msg.builder);
|
||||
originAttributes(message, msg.builder, transport);
|
||||
originAttributes(message, msg.builder, transport, threadPool.getThreadContext());
|
||||
|
||||
if (action != null) {
|
||||
msg.builder.field(Field.ACTION, action);
|
||||
|
@ -557,7 +558,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
|||
|
||||
Message msg = new Message().start();
|
||||
common("transport", type, msg.builder);
|
||||
originAttributes(message, msg.builder, transport);
|
||||
originAttributes(message, msg.builder, transport, threadPool.getThreadContext());
|
||||
|
||||
if (action != null) {
|
||||
msg.builder.field(Field.ACTION, action);
|
||||
|
@ -631,10 +632,10 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
|||
return builder;
|
||||
}
|
||||
|
||||
private static XContentBuilder originAttributes(TransportMessage message, XContentBuilder builder, Transport transport) throws IOException {
|
||||
private static XContentBuilder originAttributes(TransportMessage message, XContentBuilder builder, Transport transport, ThreadContext threadContext) throws IOException {
|
||||
|
||||
// first checking if the message originated in a rest call
|
||||
InetSocketAddress restAddress = RemoteHostHeader.restRemoteAddress(message);
|
||||
InetSocketAddress restAddress = RemoteHostHeader.restRemoteAddress(threadContext);
|
||||
if (restAddress != null) {
|
||||
builder.field(Field.ORIGIN_TYPE, "rest");
|
||||
builder.field(Field.ORIGIN_ADDRESS, NetworkAddress.formatAddress(restAddress.getAddress()));
|
||||
|
@ -677,7 +678,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
|||
private void initializeClient() {
|
||||
if (indexToRemoteCluster == false) {
|
||||
// in the absence of client settings for remote indexing, fall back to the client that was passed in.
|
||||
this.client = clientProvider.get();
|
||||
this.client = new ClientWithUser(clientProvider.get(), authenticationService, auditUser.user());
|
||||
} else {
|
||||
Settings clientSettings = settings.getByPrefix("shield.audit.index.client.");
|
||||
String[] hosts = clientSettings.getAsArray("hosts");
|
||||
|
@ -763,7 +764,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
|||
assert !Thread.currentThread().isInterrupted() : "current thread has been interrupted before putting index template!!!";
|
||||
|
||||
if (!indexToRemoteCluster) {
|
||||
authenticationService.attachUserHeaderIfMissing(request, auditUser.user());
|
||||
authenticationService.attachUserHeaderIfMissing(auditUser.user());
|
||||
}
|
||||
PutIndexTemplateResponse response = client.admin().indices().putTemplate(request).actionGet();
|
||||
if (!response.isAcknowledged()) {
|
||||
|
@ -780,18 +781,10 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
|||
}
|
||||
String index = resolve(INDEX_NAME_PREFIX, dateTime, rollover);
|
||||
IndicesExistsRequest existsRequest = new IndicesExistsRequest(index);
|
||||
// TODO need to clean this up so we don't forget to attach the header...
|
||||
if (!indexToRemoteCluster) {
|
||||
authenticationService.attachUserHeaderIfMissing(existsRequest, auditUser.user());
|
||||
}
|
||||
|
||||
if (client.admin().indices().exists(existsRequest).get().isExists()) {
|
||||
logger.debug("index [{}] exists so we need to update mappings", index);
|
||||
PutMappingRequest putMappingRequest = new PutMappingRequest(index).type(DOC_TYPE).source(request.mappings().get(DOC_TYPE));
|
||||
if (!indexToRemoteCluster) {
|
||||
authenticationService.attachUserHeaderIfMissing(putMappingRequest, auditUser.user());
|
||||
}
|
||||
|
||||
PutMappingResponse putMappingResponse = client.admin().indices().putMapping(putMappingRequest).get();
|
||||
if (!putMappingResponse.isAcknowledged()) {
|
||||
throw new IllegalStateException("failed to put mappings for audit logging index [" + index + "]");
|
||||
|
@ -815,15 +808,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
|||
|
||||
bulkProcessor = BulkProcessor.builder(client, new BulkProcessor.Listener() {
|
||||
@Override
|
||||
public void beforeBulk(long executionId, BulkRequest request) {
|
||||
try {
|
||||
if (!indexToRemoteCluster) {
|
||||
authenticationService.attachUserHeaderIfMissing(request, auditUser.user());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("failed to attach user header", e);
|
||||
}
|
||||
}
|
||||
public void beforeBulk(long executionId, BulkRequest request) {}
|
||||
|
||||
@Override
|
||||
public void afterBulk(long executionId, BulkRequest request, BulkResponse response) {
|
||||
|
@ -895,9 +880,6 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
|||
IndexRequest indexRequest = client.prepareIndex()
|
||||
.setIndex(resolve(INDEX_NAME_PREFIX, message.timestamp, rollover))
|
||||
.setType(DOC_TYPE).setSource(message.builder).request();
|
||||
if (!indexToRemoteCluster) {
|
||||
authenticationService.attachUserHeaderIfMissing(indexRequest, auditUser.user());
|
||||
}
|
||||
bulkProcessor.add(indexRequest);
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("index audit queue consumer interrupted", e);
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.common.network.NetworkAddress;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.admin.ShieldInternalUserHolder;
|
||||
|
@ -24,6 +25,7 @@ import org.elasticsearch.shield.authz.privilege.Privilege;
|
|||
import org.elasticsearch.shield.authz.privilege.SystemPrivilege;
|
||||
import org.elasticsearch.shield.rest.RemoteHostHeader;
|
||||
import org.elasticsearch.shield.transport.filter.ShieldIpFilterRule;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
|
||||
|
@ -44,6 +46,7 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
|
||||
private final ESLogger logger;
|
||||
private final Transport transport;
|
||||
private final ThreadContext threadContext;
|
||||
|
||||
private String prefix;
|
||||
|
||||
|
@ -53,19 +56,20 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
}
|
||||
|
||||
@Inject
|
||||
public LoggingAuditTrail(Settings settings, Transport transport) {
|
||||
this(settings, transport, Loggers.getLogger(LoggingAuditTrail.class));
|
||||
public LoggingAuditTrail(Settings settings, Transport transport, ThreadPool threadPool) {
|
||||
this(settings, transport, Loggers.getLogger(LoggingAuditTrail.class), threadPool.getThreadContext());
|
||||
}
|
||||
|
||||
LoggingAuditTrail(Settings settings, Transport transport, ESLogger logger) {
|
||||
this("", settings, transport, logger);
|
||||
LoggingAuditTrail(Settings settings, Transport transport, ESLogger logger, ThreadContext threadContext) {
|
||||
this("", settings, transport, logger, threadContext);
|
||||
}
|
||||
|
||||
LoggingAuditTrail(String prefix, Settings settings, Transport transport, ESLogger logger) {
|
||||
LoggingAuditTrail(String prefix, Settings settings, Transport transport, ESLogger logger, ThreadContext threadContext) {
|
||||
super(settings);
|
||||
this.logger = logger;
|
||||
this.prefix = prefix;
|
||||
this.transport = transport;
|
||||
this.threadContext = threadContext;
|
||||
}
|
||||
|
||||
|
||||
|
@ -96,15 +100,15 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
String indices = indicesString(message);
|
||||
if (indices != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [anonymous_access_denied]\t{}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport), action, indices, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [anonymous_access_denied]\t{}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), action, indices, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.warn("{}[transport] [anonymous_access_denied]\t{}, action=[{}], indices=[{}]", prefix, originAttributes(message, transport), action, indices);
|
||||
logger.warn("{}[transport] [anonymous_access_denied]\t{}, action=[{}], indices=[{}]", prefix, originAttributes(message, transport, threadContext), action, indices);
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [anonymous_access_denied]\t{}, action=[{}], request=[{}]", prefix, originAttributes(message, transport), action, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [anonymous_access_denied]\t{}, action=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), action, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.warn("{}[transport] [anonymous_access_denied]\t{}, action=[{}]", prefix, originAttributes(message, transport), action);
|
||||
logger.warn("{}[transport] [anonymous_access_denied]\t{}, action=[{}]", prefix, originAttributes(message, transport, threadContext), action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,15 +127,15 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
String indices = indicesString(message);
|
||||
if (indices != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport), token.principal(), action, indices, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), token.principal(), action, indices, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.error("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], indices=[{}]", prefix, originAttributes(message, transport), token.principal(), action, indices);
|
||||
logger.error("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], indices=[{}]", prefix, originAttributes(message, transport, threadContext), token.principal(), action, indices);
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], request=[{}]", prefix, originAttributes(message, transport), token.principal(), action, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), token.principal(), action, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.error("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}]", prefix, originAttributes(message, transport), token.principal(), action);
|
||||
logger.error("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}]", prefix, originAttributes(message, transport, threadContext), token.principal(), action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,15 +154,15 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
String indices = indicesString(message);
|
||||
if (indices != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [authentication_failed]\t{}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport), action, indices, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [authentication_failed]\t{}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), action, indices, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.error("{}[transport] [authentication_failed]\t{}, action=[{}], indices=[{}]", prefix, originAttributes(message, transport), action, indices);
|
||||
logger.error("{}[transport] [authentication_failed]\t{}, action=[{}], indices=[{}]", prefix, originAttributes(message, transport, threadContext), action, indices);
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [authentication_failed]\t{}, action=[{}], request=[{}]", prefix, originAttributes(message, transport), action, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [authentication_failed]\t{}, action=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), action, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.error("{}[transport] [authentication_failed]\t{}, action=[{}]", prefix, originAttributes(message, transport), action);
|
||||
logger.error("{}[transport] [authentication_failed]\t{}, action=[{}]", prefix, originAttributes(message, transport, threadContext), action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,9 +181,9 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
if (logger.isTraceEnabled()) {
|
||||
String indices = indicesString(message);
|
||||
if (indices != null) {
|
||||
logger.trace("{}[transport] [authentication_failed]\trealm=[{}], {}, principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, realm, originAttributes(message, transport), token.principal(), action, indices, message.getClass().getSimpleName());
|
||||
logger.trace("{}[transport] [authentication_failed]\trealm=[{}], {}, principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, realm, originAttributes(message, transport, threadContext), token.principal(), action, indices, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.trace("{}[transport] [authentication_failed]\trealm=[{}], {}, principal=[{}], action=[{}], request=[{}]", prefix, realm, originAttributes(message, transport), token.principal(), action, message.getClass().getSimpleName());
|
||||
logger.trace("{}[transport] [authentication_failed]\trealm=[{}], {}, principal=[{}], action=[{}], request=[{}]", prefix, realm, originAttributes(message, transport, threadContext), token.principal(), action, message.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -199,9 +203,9 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
if ((user.isSystem() && SystemPrivilege.INSTANCE.predicate().test(action)) || ShieldInternalUserHolder.isShieldInternalUser(user)) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
if (indices != null) {
|
||||
logger.trace("{}[transport] [access_granted]\t{}, {}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport), principal(user), action, indices, message.getClass().getSimpleName());
|
||||
logger.trace("{}[transport] [access_granted]\t{}, {}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), principal(user), action, indices, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.trace("{}[transport] [access_granted]\t{}, {}, action=[{}], request=[{}]", prefix, originAttributes(message, transport), principal(user), action, message.getClass().getSimpleName());
|
||||
logger.trace("{}[transport] [access_granted]\t{}, {}, action=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), principal(user), action, message.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -209,15 +213,15 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
|
||||
if (indices != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [access_granted]\t{}, {}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport), principal(user), action, indices, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [access_granted]\t{}, {}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), principal(user), action, indices, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.info("{}[transport] [access_granted]\t{}, {}, action=[{}], indices=[{}]", prefix, originAttributes(message, transport), principal(user), action, indices);
|
||||
logger.info("{}[transport] [access_granted]\t{}, {}, action=[{}], indices=[{}]", prefix, originAttributes(message, transport, threadContext), principal(user), action, indices);
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [access_granted]\t{}, {}, action=[{}], request=[{}]", prefix, originAttributes(message, transport), principal(user), action, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [access_granted]\t{}, {}, action=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), principal(user), action, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.info("{}[transport] [access_granted]\t{}, {}, action=[{}]", prefix, originAttributes(message, transport), principal(user), action);
|
||||
logger.info("{}[transport] [access_granted]\t{}, {}, action=[{}]", prefix, originAttributes(message, transport, threadContext), principal(user), action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -227,15 +231,15 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
String indices = indicesString(message);
|
||||
if (indices != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [access_denied]\t{}, {}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport), principal(user), action, indices, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [access_denied]\t{}, {}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), principal(user), action, indices, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.error("{}[transport] [access_denied]\t{}, {}, action=[{}], indices=[{}]", prefix, originAttributes(message, transport), principal(user), action, indices);
|
||||
logger.error("{}[transport] [access_denied]\t{}, {}, action=[{}], indices=[{}]", prefix, originAttributes(message, transport, threadContext), principal(user), action, indices);
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [access_denied]\t{}, {}, action=[{}], request=[{}]", prefix, originAttributes(message, transport), principal(user), action, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [access_denied]\t{}, {}, action=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), principal(user), action, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.error("{}[transport] [access_denied]\t{}, {}, action=[{}]", prefix, originAttributes(message, transport), principal(user), action);
|
||||
logger.error("{}[transport] [access_denied]\t{}, {}, action=[{}]", prefix, originAttributes(message, transport, threadContext), principal(user), action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -245,15 +249,15 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
String indices = indicesString(message);
|
||||
if (indices != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [tampered_request]\t{}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport), action, indices, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [tampered_request]\t{}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), action, indices, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.error("{}[transport] [tampered_request]\t{}, action=[{}], indices=[{}]", prefix, originAttributes(message, transport), action, indices);
|
||||
logger.error("{}[transport] [tampered_request]\t{}, action=[{}], indices=[{}]", prefix, originAttributes(message, transport, threadContext), action, indices);
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [tampered_request]\t{}, action=[{}], request=[{}]", prefix, originAttributes(message, transport), action, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [tampered_request]\t{}, action=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), action, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.error("{}[transport] [tampered_request]\t{}, action=[{}]", prefix, originAttributes(message, transport), action);
|
||||
logger.error("{}[transport] [tampered_request]\t{}, action=[{}]", prefix, originAttributes(message, transport, threadContext), action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -263,15 +267,15 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
String indices = indicesString(request);
|
||||
if (indices != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [tampered_request]\t{}, {}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(request, transport), principal(user), action, indices, request.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [tampered_request]\t{}, {}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(request, transport, threadContext), principal(user), action, indices, request.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.error("{}[transport] [tampered_request]\t{}, {}, action=[{}], indices=[{}]", prefix, originAttributes(request, transport), principal(user), action, indices);
|
||||
logger.error("{}[transport] [tampered_request]\t{}, {}, action=[{}], indices=[{}]", prefix, originAttributes(request, transport, threadContext), principal(user), action, indices);
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [tampered_request]\t{}, {}, action=[{}], request=[{}]", prefix, originAttributes(request, transport), principal(user), action, request.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [tampered_request]\t{}, {}, action=[{}], request=[{}]", prefix, originAttributes(request, transport, threadContext), principal(user), action, request.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.error("{}[transport] [tampered_request]\t{}, {}, action=[{}]", prefix, originAttributes(request, transport), principal(user), action);
|
||||
logger.error("{}[transport] [tampered_request]\t{}, {}, action=[{}]", prefix, originAttributes(request, transport, threadContext), principal(user), action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -291,18 +295,18 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
@Override
|
||||
public void runAsGranted(User user, String action, TransportMessage<?> message) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [run_as_granted]\t{}, principal=[{}], run_as_principal=[{}], action=[{}], request=[{}]", prefix, originAttributes(message, transport), user.principal(), user.runAs().principal(), action, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [run_as_granted]\t{}, principal=[{}], run_as_principal=[{}], action=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), user.principal(), user.runAs().principal(), action, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.info("{}[transport] [run_as_granted]\t{}, principal=[{}], run_as_principal=[{}], action=[{}]", prefix, originAttributes(message, transport), user.principal(), user.runAs().principal(), action);
|
||||
logger.info("{}[transport] [run_as_granted]\t{}, principal=[{}], run_as_principal=[{}], action=[{}]", prefix, originAttributes(message, transport, threadContext), user.principal(), user.runAs().principal(), action);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(User user, String action, TransportMessage<?> message) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{}[transport] [run_as_denied]\t{}, principal=[{}], run_as_principal=[{}], action=[{}], request=[{}]", prefix, originAttributes(message, transport), user.principal(), user.runAs().principal(), action, message.getClass().getSimpleName());
|
||||
logger.debug("{}[transport] [run_as_denied]\t{}, principal=[{}], run_as_principal=[{}], action=[{}], request=[{}]", prefix, originAttributes(message, transport, threadContext), user.principal(), user.runAs().principal(), action, message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.info("{}[transport] [run_as_denied]\t{}, principal=[{}], run_as_principal=[{}], action=[{}]", prefix, originAttributes(message, transport), user.principal(), user.runAs().principal(), action);
|
||||
logger.info("{}[transport] [run_as_denied]\t{}, principal=[{}], run_as_principal=[{}], action=[{}]", prefix, originAttributes(message, transport, threadContext), user.principal(), user.runAs().principal(), action);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,11 +321,11 @@ public class LoggingAuditTrail extends AbstractLifecycleComponent<LoggingAuditTr
|
|||
return "origin_address=[" + formattedAddress + "]";
|
||||
}
|
||||
|
||||
static String originAttributes(TransportMessage message, Transport transport) {
|
||||
static String originAttributes(TransportMessage message, Transport transport, ThreadContext threadContext) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
// first checking if the message originated in a rest call
|
||||
InetSocketAddress restAddress = RemoteHostHeader.restRemoteAddress(message);
|
||||
InetSocketAddress restAddress = RemoteHostHeader.restRemoteAddress(threadContext);
|
||||
if (restAddress != null) {
|
||||
builder.append("origin_type=[rest], origin_address=[").append(NetworkAddress.formatAddress(restAddress.getAddress())).append("]");
|
||||
return builder.toString();
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package org.elasticsearch.shield.authc;
|
||||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.common.ContextAndHeaderHolder;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
|
@ -27,8 +26,9 @@ public interface AuthenticationService {
|
|||
* @return The authenticated user
|
||||
* @throws ElasticsearchSecurityException If no user was associated with the request or if the associated
|
||||
* user credentials were found to be invalid
|
||||
* @throws IOException If an error occurs when reading or writing
|
||||
*/
|
||||
User authenticate(RestRequest request) throws ElasticsearchSecurityException;
|
||||
User authenticate(RestRequest request) throws IOException, ElasticsearchSecurityException;
|
||||
|
||||
/**
|
||||
* Authenticates the user that is associated with the given message. If the user was authenticated successfully (i.e.
|
||||
|
@ -55,8 +55,7 @@ public interface AuthenticationService {
|
|||
* Checks if there's already a user header attached to the given message. If missing, a new header is
|
||||
* set on the message with the given user (encoded).
|
||||
*
|
||||
* @param message The message
|
||||
* @param user The user to be attached if the header is missing
|
||||
*/
|
||||
void attachUserHeaderIfMissing(ContextAndHeaderHolder message, User user) throws IOException;
|
||||
void attachUserHeaderIfMissing(User user) throws IOException;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ package org.elasticsearch.shield.authc;
|
|||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.common.Base64;
|
||||
import org.elasticsearch.common.ContextAndHeaderHolder;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
|
@ -15,10 +14,12 @@ import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
|||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.audit.AuditTrail;
|
||||
import org.elasticsearch.shield.crypto.CryptoService;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -44,32 +45,35 @@ public class InternalAuthenticationService extends AbstractComponent implements
|
|||
private final CryptoService cryptoService;
|
||||
private final AnonymousService anonymousService;
|
||||
private final AuthenticationFailureHandler failureHandler;
|
||||
private final ThreadContext threadContext;
|
||||
private final boolean signUserHeader;
|
||||
private final boolean runAsEnabled;
|
||||
|
||||
@Inject
|
||||
public InternalAuthenticationService(Settings settings, Realms realms, AuditTrail auditTrail, CryptoService cryptoService,
|
||||
AnonymousService anonymousService, AuthenticationFailureHandler failureHandler) {
|
||||
AnonymousService anonymousService, AuthenticationFailureHandler failureHandler,
|
||||
ThreadPool threadPool) {
|
||||
super(settings);
|
||||
this.realms = realms;
|
||||
this.auditTrail = auditTrail;
|
||||
this.cryptoService = cryptoService;
|
||||
this.anonymousService = anonymousService;
|
||||
this.failureHandler = failureHandler;
|
||||
this.threadContext = threadPool.getThreadContext();
|
||||
this.signUserHeader = settings.getAsBoolean(SETTING_SIGN_USER_HEADER, true);
|
||||
this.runAsEnabled = settings.getAsBoolean(SETTING_RUN_AS_ENABLED, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User authenticate(RestRequest request) throws ElasticsearchSecurityException {
|
||||
User user = getUserFromContext(request);
|
||||
public User authenticate(RestRequest request) throws IOException, ElasticsearchSecurityException {
|
||||
User user = getUserFromContext();
|
||||
if (user != null) {
|
||||
return user;
|
||||
}
|
||||
|
||||
AuthenticationToken token;
|
||||
try {
|
||||
token = token(request);
|
||||
token = token();
|
||||
} catch (Exception e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("failed to extract token from request", e);
|
||||
|
@ -84,7 +88,7 @@ public class InternalAuthenticationService extends AbstractComponent implements
|
|||
if (anonymousService.enabled()) {
|
||||
// we must put the user in the request context, so it'll be copied to the
|
||||
// transport request - without it, the transport will assume system user
|
||||
request.putInContext(USER_KEY, anonymousService.anonymousUser());
|
||||
putUserInContext(anonymousService.anonymousUser());
|
||||
return anonymousService.anonymousUser();
|
||||
}
|
||||
auditTrail.anonymousAccessDenied(request);
|
||||
|
@ -144,17 +148,17 @@ public class InternalAuthenticationService extends AbstractComponent implements
|
|||
|
||||
// we must put the user in the request context, so it'll be copied to the
|
||||
// transport request - without it, the transport will assume system user
|
||||
request.putInContext(USER_KEY, user);
|
||||
putUserInContext(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User authenticate(String action, TransportMessage message, User fallbackUser) throws IOException {
|
||||
User user = getUserFromContext(message);
|
||||
User user = getUserFromContext();
|
||||
if (user != null) {
|
||||
return user;
|
||||
}
|
||||
String header = message.getHeader(USER_KEY);
|
||||
String header = threadContext.getHeader(USER_KEY);
|
||||
if (header != null) {
|
||||
if (signUserHeader) {
|
||||
try {
|
||||
|
@ -168,36 +172,46 @@ public class InternalAuthenticationService extends AbstractComponent implements
|
|||
}
|
||||
if (user == null) {
|
||||
user = authenticateWithRealms(action, message, fallbackUser);
|
||||
header = signUserHeader ? cryptoService.sign(encodeUser(user, logger)) : encodeUser(user, logger);
|
||||
message.putHeader(USER_KEY, header);
|
||||
setUserHeader(user);
|
||||
}
|
||||
message.putInContext(USER_KEY, user);
|
||||
putUserInContext(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachUserHeaderIfMissing(ContextAndHeaderHolder message, User user) throws IOException {
|
||||
if (message.hasHeader(USER_KEY)) {
|
||||
public void attachUserHeaderIfMissing(User user) throws IOException {
|
||||
if (threadContext.getHeader(USER_KEY) != null) {
|
||||
return;
|
||||
}
|
||||
User userFromContext = message.getFromContext(USER_KEY);
|
||||
if (userFromContext != null) {
|
||||
String userHeader = signUserHeader ? cryptoService.sign(encodeUser(userFromContext, logger)) : encodeUser(userFromContext, logger);
|
||||
message.putHeader(USER_KEY, userHeader);
|
||||
User transientUser = threadContext.getTransient(USER_KEY);
|
||||
if (transientUser != null) {
|
||||
setUserHeader(transientUser);
|
||||
return;
|
||||
}
|
||||
|
||||
message.putInContext(USER_KEY, user);
|
||||
String userHeader = signUserHeader ? cryptoService.sign(encodeUser(user, logger)) : encodeUser(user, logger);
|
||||
message.putHeader(USER_KEY, userHeader);
|
||||
setUser(user);
|
||||
}
|
||||
|
||||
User getUserFromContext(ContextAndHeaderHolder message) {
|
||||
User user = message.getFromContext(USER_KEY);
|
||||
if (user != null) {
|
||||
return user;
|
||||
void setUserHeader(User user) throws IOException {
|
||||
String userHeader = signUserHeader ? cryptoService.sign(encodeUser(user, logger)) : encodeUser(user, logger);
|
||||
threadContext.putHeader(USER_KEY, userHeader);
|
||||
}
|
||||
|
||||
void setUser(User user) throws IOException {
|
||||
putUserInContext(user);
|
||||
setUserHeader(user);
|
||||
}
|
||||
|
||||
void putUserInContext(User user) {
|
||||
if (threadContext.getTransient(USER_KEY) != null) {
|
||||
User ctxUser = threadContext.getTransient(USER_KEY);
|
||||
throw new IllegalArgumentException("context already has user [" + ctxUser.principal() + "]. trying to set user [" + user.principal() + "]");
|
||||
}
|
||||
return null;
|
||||
threadContext.putTransient(USER_KEY, user);
|
||||
}
|
||||
|
||||
User getUserFromContext() {
|
||||
return threadContext.getTransient(USER_KEY);
|
||||
}
|
||||
|
||||
static User decodeUser(String text) {
|
||||
|
@ -283,7 +297,7 @@ public class InternalAuthenticationService extends AbstractComponent implements
|
|||
}
|
||||
|
||||
if (runAsEnabled) {
|
||||
String runAsUsername = message.getHeader(RUN_AS_USER_HEADER);
|
||||
String runAsUsername = threadContext.getHeader(RUN_AS_USER_HEADER);
|
||||
if (runAsUsername != null) {
|
||||
if (runAsUsername.isEmpty()) {
|
||||
logger.warn("user [{}] attempted to runAs with an empty username", user.principal());
|
||||
|
@ -359,11 +373,12 @@ public class InternalAuthenticationService extends AbstractComponent implements
|
|||
}
|
||||
}
|
||||
|
||||
AuthenticationToken token(RestRequest request) throws ElasticsearchSecurityException {
|
||||
AuthenticationToken token() throws ElasticsearchSecurityException {
|
||||
assert threadContext.getTransient(TOKEN_KEY) == null;
|
||||
for (Realm realm : realms) {
|
||||
AuthenticationToken token = realm.token(request);
|
||||
AuthenticationToken token = realm.token(threadContext);
|
||||
if (token != null) {
|
||||
request.putInContext(TOKEN_KEY, token);
|
||||
threadContext.putTransient(TOKEN_KEY, token);
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
@ -372,19 +387,19 @@ public class InternalAuthenticationService extends AbstractComponent implements
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
AuthenticationToken token(String action, TransportMessage<?> message) {
|
||||
AuthenticationToken token = message.getFromContext(TOKEN_KEY);
|
||||
AuthenticationToken token = threadContext.getTransient(TOKEN_KEY);
|
||||
if (token != null) {
|
||||
return token;
|
||||
}
|
||||
for (Realm realm : realms) {
|
||||
token = realm.token(message);
|
||||
token = realm.token(threadContext);
|
||||
if (token != null) {
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("realm [{}] resolved authentication token [{}] from transport request with action [{}]", realm, token.principal(), action);
|
||||
}
|
||||
|
||||
message.putInContext(TOKEN_KEY, token);
|
||||
threadContext.putTransient(TOKEN_KEY, token);
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,9 @@
|
|||
package org.elasticsearch.shield.authc;
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.ShieldSettingsFilter;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
|
||||
/**
|
||||
* An authentication mechanism to which the default authentication {@link org.elasticsearch.shield.authc.AuthenticationService service}
|
||||
|
@ -60,22 +59,13 @@ public abstract class Realm<T extends AuthenticationToken> implements Comparable
|
|||
public abstract boolean supports(AuthenticationToken token);
|
||||
|
||||
/**
|
||||
* Attempts to extract an authentication token from the given rest request. If an appropriate token
|
||||
* Attempts to extract an authentication token from the given context. If an appropriate token
|
||||
* is found it's returned, otherwise {@code null} is returned.
|
||||
*
|
||||
* @param request The rest request
|
||||
* @param context The context that will provide information about the incoming request
|
||||
* @return The authentication token or {@code null} if not found
|
||||
*/
|
||||
public abstract T token(RestRequest request);
|
||||
|
||||
/**
|
||||
* Attempts to extract an authentication token from the given transport message. If an appropriate token
|
||||
* is found it's returned, otherwise {@code null} is returned.
|
||||
*
|
||||
* @param message The transport message
|
||||
* @return The authentication token or {@code null} if not found
|
||||
*/
|
||||
public abstract T token(TransportMessage<?> message);
|
||||
public abstract T token(ThreadContext context);
|
||||
|
||||
/**
|
||||
* Authenticates the given token. A successful authentication will return the User associated
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.shield.authc.activedirectory;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.shield.ShieldSettingsFilter;
|
||||
import org.elasticsearch.shield.authc.RealmConfig;
|
||||
import org.elasticsearch.shield.authc.ldap.support.AbstractLdapRealm;
|
||||
|
@ -33,8 +34,8 @@ public class ActiveDirectoryRealm extends AbstractLdapRealm {
|
|||
private final ClientSSLService clientSSLService;
|
||||
|
||||
@Inject
|
||||
public Factory(ResourceWatcherService watcherService, ClientSSLService clientSSLService) {
|
||||
super(ActiveDirectoryRealm.TYPE);
|
||||
public Factory(ResourceWatcherService watcherService, ClientSSLService clientSSLService, RestController restController) {
|
||||
super(ActiveDirectoryRealm.TYPE, restController);
|
||||
this.watcherService = watcherService;
|
||||
this.clientSSLService = clientSSLService;
|
||||
}
|
||||
|
|
|
@ -11,9 +11,12 @@ import com.carrotsearch.hppc.ObjectLongMap;
|
|||
import com.carrotsearch.hppc.cursors.ObjectCursor;
|
||||
import com.carrotsearch.hppc.cursors.ObjectLongCursor;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionRequestBuilder;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.action.LatchedActionListener;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
import org.elasticsearch.action.delete.DeleteResponse;
|
||||
|
@ -27,6 +30,7 @@ import org.elasticsearch.action.search.SearchRequest;
|
|||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.action.search.SearchScrollRequest;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.FilterClient;
|
||||
import org.elasticsearch.cluster.ClusterChangedEvent;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.ClusterStateListener;
|
||||
|
@ -40,11 +44,11 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
|
||||
import org.elasticsearch.common.util.concurrent.FutureUtils;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.gateway.GatewayService;
|
||||
import org.elasticsearch.index.IndexNotFoundException;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.action.admin.user.AddUserRequest;
|
||||
|
@ -57,8 +61,8 @@ import org.elasticsearch.shield.authc.AuthenticationService;
|
|||
import org.elasticsearch.shield.authc.support.Hasher;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.client.ShieldClient;
|
||||
import org.elasticsearch.shield.support.ClientWithUser;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -116,16 +120,6 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
this.threadPool = threadPool;
|
||||
}
|
||||
|
||||
private final void attachUser(TransportMessage message) {
|
||||
try {
|
||||
authService.attachUserHeaderIfMissing(message, adminUser.user());
|
||||
} catch (IOException e) {
|
||||
logger.error("failed to attach authorization to internal message!", e);
|
||||
throw new ElasticsearchSecurityException("unable to attach administrative user to transport message",
|
||||
RestStatus.SERVICE_UNAVAILABLE, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private UserAndPassword transformUser(Map<String, Object> sourceMap) {
|
||||
if (sourceMap == null) {
|
||||
|
@ -207,7 +201,6 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
.setSize(scrollSize)
|
||||
.setFetchSource(true)
|
||||
.request();
|
||||
attachUser(request);
|
||||
request.indicesOptions().ignoreUnavailable();
|
||||
|
||||
// This function is MADNESS! But it works, don't think about it too hard...
|
||||
|
@ -224,11 +217,9 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
}
|
||||
SearchScrollRequest scrollRequest = client.prepareSearchScroll(resp.getScrollId())
|
||||
.setScroll(scrollKeepAlive).request();
|
||||
attachUser(scrollRequest);
|
||||
client.searchScroll(scrollRequest, this);
|
||||
} else {
|
||||
ClearScrollRequest clearScrollRequest = client.prepareClearScroll().addScrollId(resp.getScrollId()).request();
|
||||
attachUser(clearScrollRequest);
|
||||
client.clearScroll(clearScrollRequest, new ActionListener<ClearScrollResponse>() {
|
||||
@Override
|
||||
public void onResponse(ClearScrollResponse response) {
|
||||
|
@ -291,7 +282,6 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
try {
|
||||
GetRequest request = client.prepareGet(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME, INDEX_USER_TYPE, user).request();
|
||||
request.indicesOptions().ignoreUnavailable();
|
||||
attachUser(request);
|
||||
client.get(request, new ActionListener<GetResponse>() {
|
||||
@Override
|
||||
public void onResponse(GetResponse getFields) {
|
||||
|
@ -332,7 +322,6 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
"password", String.valueOf(addUserRequest.passwordHash()),
|
||||
"roles", addUserRequest.roles())
|
||||
.request();
|
||||
attachUser(request);
|
||||
|
||||
client.index(request, new ActionListener<IndexResponse>() {
|
||||
@Override
|
||||
|
@ -367,7 +356,6 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
DeleteRequest request = client.prepareDelete(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME,
|
||||
INDEX_USER_TYPE, deleteUserRequest.user()).request();
|
||||
request.indicesOptions().ignoreUnavailable();
|
||||
attachUser(request);
|
||||
client.delete(request, new ActionListener<DeleteResponse>() {
|
||||
@Override
|
||||
public void onResponse(DeleteResponse deleteResponse) {
|
||||
|
@ -420,8 +408,8 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
public void start() {
|
||||
try {
|
||||
if (state.compareAndSet(State.INITIALIZED, State.STARTING)) {
|
||||
this.client = clientProvider.get();
|
||||
this.authService = authProvider.get();
|
||||
this.client = new ClientWithUser(clientProvider.get(), authService, adminUser.user());
|
||||
this.scrollSize = settings.getAsInt("shield.authc.native.scroll.size", 1000);
|
||||
this.scrollKeepAlive = settings.getAsTime("shield.authc.native.scroll.keep_alive", TimeValue.timeValueSeconds(10L));
|
||||
|
||||
|
@ -484,7 +472,6 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
ShieldClient shieldClient = new ShieldClient(client);
|
||||
ClearRealmCacheRequest request = shieldClient.prepareClearRealmCache()
|
||||
.usernames(username).request();
|
||||
attachUser(request);
|
||||
shieldClient.clearRealmCache(request, new ActionListener<ClearRealmCacheResponse>() {
|
||||
@Override
|
||||
public void onResponse(ClearRealmCacheResponse nodes) {
|
||||
|
@ -628,7 +615,6 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
.setVersion(true)
|
||||
.setFetchSource(true)
|
||||
.request();
|
||||
attachUser(request);
|
||||
response = client.search(request).actionGet();
|
||||
|
||||
boolean keepScrolling = response.getHits().getHits().length > 0;
|
||||
|
@ -639,7 +625,6 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
map.put(username, version);
|
||||
}
|
||||
SearchScrollRequest scrollRequest = client.prepareSearchScroll(response.getScrollId()).setScroll(scrollKeepAlive).request();
|
||||
attachUser(scrollRequest);
|
||||
response = client.searchScroll(scrollRequest).actionGet();
|
||||
keepScrolling = response.getHits().getHits().length > 0;
|
||||
}
|
||||
|
@ -648,7 +633,6 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
} finally {
|
||||
if (response != null) {
|
||||
ClearScrollRequest clearScrollRequest = client.prepareClearScroll().addScrollId(response.getScrollId()).request();
|
||||
attachUser(clearScrollRequest);
|
||||
client.clearScroll(clearScrollRequest).actionGet();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,12 @@ package org.elasticsearch.shield.authc.esusers;
|
|||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.authc.Realm;
|
||||
import org.elasticsearch.shield.authc.RealmConfig;
|
||||
import org.elasticsearch.shield.authc.support.CachingUsernamePasswordRealm;
|
||||
import org.elasticsearch.shield.authc.support.RefreshListener;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordRealm;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
|
||||
|
@ -66,15 +67,15 @@ public class ESUsersRealm extends CachingUsernamePasswordRealm {
|
|||
}
|
||||
}
|
||||
|
||||
public static class Factory extends Realm.Factory<ESUsersRealm> {
|
||||
public static class Factory extends UsernamePasswordRealm.Factory<ESUsersRealm> {
|
||||
|
||||
private final Settings settings;
|
||||
private final Environment env;
|
||||
private final ResourceWatcherService watcherService;
|
||||
|
||||
@Inject
|
||||
public Factory(Settings settings, Environment env, ResourceWatcherService watcherService) {
|
||||
super(TYPE, true);
|
||||
public Factory(Settings settings, Environment env, ResourceWatcherService watcherService, RestController restController) {
|
||||
super(TYPE, restController, true);
|
||||
this.settings = settings;
|
||||
this.env = env;
|
||||
this.watcherService = watcherService;
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.shield.authc.ldap;
|
|||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.shield.ShieldSettingsFilter;
|
||||
import org.elasticsearch.shield.authc.RealmConfig;
|
||||
import org.elasticsearch.shield.authc.ldap.support.AbstractLdapRealm;
|
||||
|
@ -35,8 +36,8 @@ public class LdapRealm extends AbstractLdapRealm {
|
|||
private final ClientSSLService clientSSLService;
|
||||
|
||||
@Inject
|
||||
public Factory(ResourceWatcherService watcherService, ClientSSLService clientSSLService) {
|
||||
super(TYPE);
|
||||
public Factory(ResourceWatcherService watcherService, ClientSSLService clientSSLService, RestController restController) {
|
||||
super(TYPE, restController);
|
||||
this.watcherService = watcherService;
|
||||
this.clientSSLService = clientSSLService;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.shield.authc.ldap.support;
|
||||
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.authc.RealmConfig;
|
||||
import org.elasticsearch.shield.authc.support.CachingUsernamePasswordRealm;
|
||||
|
@ -92,8 +93,8 @@ public abstract class AbstractLdapRealm extends CachingUsernamePasswordRealm {
|
|||
|
||||
public static abstract class Factory<R extends AbstractLdapRealm> extends UsernamePasswordRealm.Factory<R> {
|
||||
|
||||
public Factory(String type) {
|
||||
super(type, false);
|
||||
public Factory(String type, RestController restController) {
|
||||
super(type, restController, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,8 +9,8 @@ import org.elasticsearch.common.Strings;
|
|||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.shield.ShieldSettingsFilter;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.authc.AuthenticationToken;
|
||||
|
@ -20,7 +20,6 @@ import org.elasticsearch.shield.authc.support.DnRoleMapper;
|
|||
import org.elasticsearch.shield.transport.SSLClientAuth;
|
||||
import org.elasticsearch.shield.transport.netty.ShieldNettyHttpServerTransport;
|
||||
import org.elasticsearch.shield.transport.netty.ShieldNettyTransport;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
@ -66,13 +65,8 @@ public class PkiRealm extends Realm<X509AuthenticationToken> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public X509AuthenticationToken token(RestRequest request) {
|
||||
return token(request.getFromContext(PKI_CERT_HEADER_NAME), principalPattern, logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509AuthenticationToken token(TransportMessage<?> message) {
|
||||
return token(message.getFromContext(PKI_CERT_HEADER_NAME), principalPattern, logger);
|
||||
public X509AuthenticationToken token(ThreadContext context) {
|
||||
return token(context.getTransient(PKI_CERT_HEADER_NAME), principalPattern, logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
*/
|
||||
package org.elasticsearch.shield.authc.support;
|
||||
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.shield.authc.AuthenticationToken;
|
||||
import org.elasticsearch.shield.authc.Realm;
|
||||
import org.elasticsearch.shield.authc.RealmConfig;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -21,13 +21,8 @@ public abstract class UsernamePasswordRealm extends Realm<UsernamePasswordToken>
|
|||
}
|
||||
|
||||
@Override
|
||||
public UsernamePasswordToken token(RestRequest request) {
|
||||
return UsernamePasswordToken.extractToken(request, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UsernamePasswordToken token(TransportMessage<?> message) {
|
||||
return UsernamePasswordToken.extractToken(message, null);
|
||||
public UsernamePasswordToken token(ThreadContext threadContext) {
|
||||
return UsernamePasswordToken.extractToken(threadContext, null);
|
||||
}
|
||||
|
||||
public boolean supports(AuthenticationToken token) {
|
||||
|
@ -36,8 +31,9 @@ public abstract class UsernamePasswordRealm extends Realm<UsernamePasswordToken>
|
|||
|
||||
public static abstract class Factory<R extends UsernamePasswordRealm> extends Realm.Factory<R> {
|
||||
|
||||
protected Factory(String type, boolean internal) {
|
||||
protected Factory(String type, RestController restController, boolean internal) {
|
||||
super(type, internal);
|
||||
restController.registerRelevantHeaders(UsernamePasswordToken.BASIC_AUTH_HEADER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,9 @@
|
|||
package org.elasticsearch.shield.authc.support;
|
||||
|
||||
import org.elasticsearch.common.Base64;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.shield.authc.AuthenticationToken;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.CharBuffer;
|
||||
|
@ -67,8 +66,8 @@ public class UsernamePasswordToken implements AuthenticationToken {
|
|||
return Objects.hash(username, password.hashCode());
|
||||
}
|
||||
|
||||
public static UsernamePasswordToken extractToken(TransportMessage<?> message, UsernamePasswordToken defaultToken) {
|
||||
String authStr = message.getHeader(BASIC_AUTH_HEADER);
|
||||
public static UsernamePasswordToken extractToken(ThreadContext context, UsernamePasswordToken defaultToken) {
|
||||
String authStr = context.getHeader(BASIC_AUTH_HEADER);
|
||||
if (authStr == null) {
|
||||
return defaultToken;
|
||||
}
|
||||
|
@ -108,8 +107,8 @@ public class UsernamePasswordToken implements AuthenticationToken {
|
|||
new SecuredString(Arrays.copyOfRange(userpasswd, i + 1, userpasswd.length)));
|
||||
}
|
||||
|
||||
public static void putTokenHeader(TransportRequest request, UsernamePasswordToken token) {
|
||||
request.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue(token.username, token.password));
|
||||
public static void putTokenHeader(ThreadContext context, UsernamePasswordToken token) {
|
||||
context.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue(token.username, token.password));
|
||||
}
|
||||
|
||||
public static String basicAuthHeaderValue(String username, SecuredString passwd) {
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.elasticsearch.cluster.metadata.MetaData;
|
|||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.search.action.SearchServiceTransportAction;
|
||||
import org.elasticsearch.shield.User;
|
||||
|
@ -35,6 +36,7 @@ import org.elasticsearch.shield.authz.permission.RunAsPermission;
|
|||
import org.elasticsearch.shield.authz.privilege.ClusterPrivilege;
|
||||
import org.elasticsearch.shield.authz.privilege.IndexPrivilege;
|
||||
import org.elasticsearch.shield.authz.store.RolesStore;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -59,10 +61,12 @@ public class InternalAuthorizationService extends AbstractComponent implements A
|
|||
private final IndicesAndAliasesResolver[] indicesAndAliasesResolvers;
|
||||
private final AnonymousService anonymousService;
|
||||
private final AuthenticationFailureHandler authcFailureHandler;
|
||||
private final ThreadContext threadContext;
|
||||
|
||||
@Inject
|
||||
public InternalAuthorizationService(Settings settings, RolesStore rolesStore, ClusterService clusterService,
|
||||
AuditTrail auditTrail, AnonymousService anonymousService, AuthenticationFailureHandler authcFailureHandler) {
|
||||
AuditTrail auditTrail, AnonymousService anonymousService,
|
||||
AuthenticationFailureHandler authcFailureHandler, ThreadPool threadPool) {
|
||||
super(settings);
|
||||
this.rolesStore = rolesStore;
|
||||
this.clusterService = clusterService;
|
||||
|
@ -72,6 +76,7 @@ public class InternalAuthorizationService extends AbstractComponent implements A
|
|||
};
|
||||
this.anonymousService = anonymousService;
|
||||
this.authcFailureHandler = authcFailureHandler;
|
||||
this.threadContext = threadPool.getThreadContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -106,7 +111,7 @@ public class InternalAuthorizationService extends AbstractComponent implements A
|
|||
// first we need to check if the user is the system. If it is, we'll just authorize the system access
|
||||
if (user.isSystem()) {
|
||||
if (SystemRole.INSTANCE.check(action)) {
|
||||
request.putInContext(INDICES_PERMISSIONS_KEY, IndicesAccessControl.ALLOW_ALL);
|
||||
setIndicesAccessControl(IndicesAccessControl.ALLOW_ALL);
|
||||
grant(user, action, request);
|
||||
return;
|
||||
}
|
||||
|
@ -149,7 +154,7 @@ public class InternalAuthorizationService extends AbstractComponent implements A
|
|||
if (ClusterPrivilege.ACTION_MATCHER.test(action)) {
|
||||
ClusterPermission cluster = permission.cluster();
|
||||
if (cluster != null && cluster.check(action)) {
|
||||
request.putInContext(INDICES_PERMISSIONS_KEY, IndicesAccessControl.ALLOW_ALL);
|
||||
setIndicesAccessControl(IndicesAccessControl.ALLOW_ALL);
|
||||
grant(user, action, request);
|
||||
return;
|
||||
}
|
||||
|
@ -191,7 +196,7 @@ public class InternalAuthorizationService extends AbstractComponent implements A
|
|||
if (!indicesAccessControl.isGranted()) {
|
||||
throw denial(user, action, request);
|
||||
} else {
|
||||
request.putInContext(INDICES_PERMISSIONS_KEY, indicesAccessControl);
|
||||
setIndicesAccessControl(indicesAccessControl);
|
||||
}
|
||||
|
||||
//if we are creating an index we need to authorize potential aliases created at the same time
|
||||
|
@ -215,6 +220,12 @@ public class InternalAuthorizationService extends AbstractComponent implements A
|
|||
grant(user, action, request);
|
||||
}
|
||||
|
||||
private void setIndicesAccessControl(IndicesAccessControl accessControl) {
|
||||
if (threadContext.getTransient(INDICES_PERMISSIONS_KEY) == null) {
|
||||
threadContext.putTransient(INDICES_PERMISSIONS_KEY, accessControl);
|
||||
}
|
||||
}
|
||||
|
||||
private GlobalPermission permission(String[] roleNames) {
|
||||
if (roleNames.length == 0) {
|
||||
return GlobalPermission.NONE;
|
||||
|
|
|
@ -45,7 +45,7 @@ public final class OptOutQueryCache extends AbstractIndexComponent implements Qu
|
|||
if (context == null) {
|
||||
throw new IllegalStateException("opting out of the query cache. current request can't be found");
|
||||
}
|
||||
final IndicesAccessControl indicesAccessControl = context.getRequest().getFromContext(InternalAuthorizationService.INDICES_PERMISSIONS_KEY);
|
||||
IndicesAccessControl indicesAccessControl = context.getThreadContext().getTransient(InternalAuthorizationService.INDICES_PERMISSIONS_KEY);
|
||||
if (indicesAccessControl == null) {
|
||||
logger.debug("opting out of the query cache. current request doesn't hold indices permissions");
|
||||
return weight;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.shield.authz.accesscontrol;
|
||||
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
|
||||
import java.util.Objects;
|
||||
|
@ -39,10 +40,12 @@ public final class RequestContext {
|
|||
current.remove();
|
||||
}
|
||||
|
||||
private final ThreadContext threadContext;
|
||||
private final TransportRequest request;
|
||||
|
||||
public RequestContext(TransportRequest request) {
|
||||
public RequestContext(TransportRequest request, ThreadContext threadContext) {
|
||||
this.request = Objects.requireNonNull(request);
|
||||
this.threadContext = Objects.requireNonNull(threadContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,4 +54,8 @@ public final class RequestContext {
|
|||
public TransportRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
public ThreadContext getThreadContext() {
|
||||
return threadContext;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.elasticsearch.common.bytes.BytesReference;
|
|||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.index.IndexSettings;
|
||||
import org.elasticsearch.index.cache.bitset.BitsetFilterCache;
|
||||
import org.elasticsearch.index.engine.EngineException;
|
||||
|
@ -56,7 +57,7 @@ import static org.apache.lucene.search.BooleanClause.Occur.FILTER;
|
|||
/**
|
||||
* An {@link IndexSearcherWrapper} implementation that is used for field and document level security.
|
||||
* <p>
|
||||
* Based on the {@link RequestContext} this class will enable field and/or document level security.
|
||||
* Based on the {@link ThreadContext} this class will enable field and/or document level security.
|
||||
* <p>
|
||||
* Field level security is enabled by wrapping the original {@link DirectoryReader} in a {@link FieldSubsetReader}
|
||||
* in the {@link #wrap(DirectoryReader)} method.
|
||||
|
@ -71,14 +72,17 @@ public class ShieldIndexSearcherWrapper extends IndexSearcherWrapper {
|
|||
private final QueryShardContext queryShardContext;
|
||||
private final BitsetFilterCache bitsetFilterCache;
|
||||
private final ShieldLicenseState shieldLicenseState;
|
||||
private final ThreadContext threadContext;
|
||||
private final ESLogger logger;
|
||||
|
||||
public ShieldIndexSearcherWrapper(IndexSettings indexSettings, QueryShardContext queryShardContext,
|
||||
MapperService mapperService, BitsetFilterCache bitsetFilterCache, ShieldLicenseState shieldLicenseState) {
|
||||
MapperService mapperService, BitsetFilterCache bitsetFilterCache,
|
||||
ThreadContext threadContext, ShieldLicenseState shieldLicenseState) {
|
||||
this.logger = Loggers.getLogger(getClass(), indexSettings.getSettings());
|
||||
this.mapperService = mapperService;
|
||||
this.queryShardContext = queryShardContext;
|
||||
this.bitsetFilterCache = bitsetFilterCache;
|
||||
this.threadContext = threadContext;
|
||||
this.shieldLicenseState = shieldLicenseState;
|
||||
|
||||
Set<String> allowedMetaFields = new HashSet<>();
|
||||
|
@ -98,15 +102,8 @@ public class ShieldIndexSearcherWrapper extends IndexSearcherWrapper {
|
|||
|
||||
final Set<String> allowedMetaFields = this.allowedMetaFields;
|
||||
try {
|
||||
RequestContext context = RequestContext.current();
|
||||
if (context == null) {
|
||||
throw new IllegalStateException("can't locate the origin of the current request");
|
||||
}
|
||||
final IndicesAccessControl indicesAccessControl = getIndicesAccessControl();
|
||||
|
||||
IndicesAccessControl indicesAccessControl = context.getRequest().getFromContext(InternalAuthorizationService.INDICES_PERMISSIONS_KEY);
|
||||
if (indicesAccessControl == null) {
|
||||
throw Exceptions.authorizationError("no indices permissions found");
|
||||
}
|
||||
ShardId shardId = ShardUtils.extractShardId(reader);
|
||||
if (shardId == null) {
|
||||
throw new IllegalStateException(LoggerMessageFormat.format("couldn't extract shardId from reader [{}]", reader));
|
||||
|
@ -245,4 +242,11 @@ public class ShieldIndexSearcherWrapper extends IndexSearcherWrapper {
|
|||
}
|
||||
}
|
||||
|
||||
protected IndicesAccessControl getIndicesAccessControl() {
|
||||
IndicesAccessControl indicesAccessControl = threadContext.getTransient(InternalAuthorizationService.INDICES_PERMISSIONS_KEY);
|
||||
if (indicesAccessControl == null) {
|
||||
throw Exceptions.authorizationError("no indices permissions found");
|
||||
}
|
||||
return indicesAccessControl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package org.elasticsearch.shield.authz.esnative;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.LatchedActionListener;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
|
@ -38,7 +37,6 @@ import org.elasticsearch.gateway.GatewayService;
|
|||
import org.elasticsearch.index.IndexNotFoundException;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.shield.action.admin.role.AddRoleRequest;
|
||||
import org.elasticsearch.shield.action.admin.role.DeleteRoleRequest;
|
||||
|
@ -51,10 +49,9 @@ import org.elasticsearch.shield.authz.permission.Role;
|
|||
import org.elasticsearch.shield.authz.RoleDescriptor;
|
||||
import org.elasticsearch.shield.authz.store.RolesStore;
|
||||
import org.elasticsearch.shield.client.ShieldClient;
|
||||
import org.elasticsearch.shield.support.ClientWithUser;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
@ -91,7 +88,6 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
|
||||
private Client client;
|
||||
private ShieldClient shieldClient;
|
||||
private AuthenticationService authService;
|
||||
private int scrollSize;
|
||||
private TimeValue scrollKeepAlive;
|
||||
private ScheduledFuture<?> versionChecker;
|
||||
|
@ -110,16 +106,6 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
this.threadPool = threadPool;
|
||||
}
|
||||
|
||||
private final void attachUser(TransportMessage message) {
|
||||
try {
|
||||
authService.attachUserHeaderIfMissing(message, adminUser.user());
|
||||
} catch (IOException e) {
|
||||
logger.error("failed to attach authorization to internal message!", e);
|
||||
throw new ElasticsearchSecurityException("unable to attach administrative user to transport message",
|
||||
RestStatus.SERVICE_UNAVAILABLE, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private RoleDescriptor transformRole(GetResponse response) {
|
||||
if (response.isExists() == false) {
|
||||
|
@ -161,7 +147,6 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
.setSize(scrollSize)
|
||||
.setFetchSource(true)
|
||||
.request();
|
||||
attachUser(request);
|
||||
request.indicesOptions().ignoreUnavailable();
|
||||
|
||||
// This function is MADNESS! But it works, don't think about it too hard...
|
||||
|
@ -178,11 +163,9 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
}
|
||||
SearchScrollRequest scrollRequest = client.prepareSearchScroll(resp.getScrollId())
|
||||
.setScroll(scrollKeepAlive).request();
|
||||
attachUser(scrollRequest);
|
||||
client.searchScroll(scrollRequest, this);
|
||||
} else {
|
||||
ClearScrollRequest clearScrollRequest = client.prepareClearScroll().addScrollId(resp.getScrollId()).request();
|
||||
attachUser(clearScrollRequest);
|
||||
client.clearScroll(clearScrollRequest, new ActionListener<ClearScrollResponse>() {
|
||||
@Override
|
||||
public void onResponse(ClearScrollResponse response) {
|
||||
|
@ -231,7 +214,6 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
try {
|
||||
GetRequest request = client.prepareGet(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME, INDEX_ROLE_TYPE, role).request();
|
||||
request.indicesOptions().ignoreUnavailable();
|
||||
attachUser(request);
|
||||
client.get(request, listener);
|
||||
} catch (Exception e) {
|
||||
logger.error("unable to retrieve role", e);
|
||||
|
@ -248,7 +230,6 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
DeleteRequest request = client.prepareDelete(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME,
|
||||
INDEX_ROLE_TYPE, deleteRoleRequest.role()).request();
|
||||
request.indicesOptions().ignoreUnavailable();
|
||||
attachUser(request);
|
||||
client.delete(request, new ActionListener<DeleteResponse>() {
|
||||
@Override
|
||||
public void onResponse(DeleteResponse deleteResponse) {
|
||||
|
@ -324,7 +305,6 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
INDEX_ROLE_TYPE, addRoleRequest.name())
|
||||
.setSource(addRoleRequest.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS))
|
||||
.request();
|
||||
attachUser(request);
|
||||
client.index(request, new ActionListener<IndexResponse>() {
|
||||
@Override
|
||||
public void onResponse(IndexResponse indexResponse) {
|
||||
|
@ -379,9 +359,8 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
public void start() {
|
||||
try {
|
||||
if (state.compareAndSet(State.INITIALIZED, State.STARTING)) {
|
||||
this.client = clientProvider.get();
|
||||
this.client = new ClientWithUser(clientProvider.get(), authProvider.get(), adminUser.user());
|
||||
this.shieldClient = new ShieldClient(client);
|
||||
this.authService = authProvider.get();
|
||||
this.scrollSize = settings.getAsInt("shield.authc.native.scroll.size", 1000);
|
||||
this.scrollKeepAlive = settings.getAsTime("shield.authc.native.scroll.keep_alive", TimeValue.timeValueSeconds(10L));
|
||||
TimeValue pollInterval = settings.getAsTime("shield.authc.native.reload.interval", TimeValue.timeValueSeconds(30L));
|
||||
|
@ -418,7 +397,6 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
}
|
||||
this.roleCache.clear();
|
||||
this.client = null;
|
||||
this.authService = null;
|
||||
this.shieldIndexExists = false;
|
||||
this.state.set(State.INITIALIZED);
|
||||
}
|
||||
|
@ -435,7 +413,6 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
|
||||
private <Response> void clearRoleCache(final String role, ActionListener<Response> listener, Response response) {
|
||||
ClearRolesCacheRequest request = new ClearRolesCacheRequest().roles(role);
|
||||
attachUser(request);
|
||||
shieldClient.clearRolesCache(request, new ActionListener<ClearRolesCacheResponse>() {
|
||||
@Override
|
||||
public void onResponse(ClearRolesCacheResponse nodes) {
|
||||
|
@ -504,7 +481,6 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
.setFetchSource(true)
|
||||
.setVersion(true)
|
||||
.request();
|
||||
attachUser(request);
|
||||
response = client.search(request).actionGet();
|
||||
|
||||
boolean keepScrolling = response.getHits().getHits().length > 0;
|
||||
|
@ -529,7 +505,6 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
});
|
||||
}
|
||||
SearchScrollRequest scrollRequest = client.prepareSearchScroll(response.getScrollId()).setScroll(scrollKeepAlive).request();
|
||||
attachUser(scrollRequest);
|
||||
response = client.searchScroll(scrollRequest).actionGet();
|
||||
keepScrolling = response.getHits().getHits().length > 0;
|
||||
}
|
||||
|
@ -545,7 +520,6 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
} finally {
|
||||
if (response != null) {
|
||||
ClearScrollRequest clearScrollRequest = client.prepareClearScroll().addScrollId(response.getScrollId()).request();
|
||||
attachUser(clearScrollRequest);
|
||||
client.clearScroll(clearScrollRequest).actionGet();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*/
|
||||
package org.elasticsearch.shield.rest;
|
||||
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
|
@ -22,23 +22,23 @@ public class RemoteHostHeader {
|
|||
* Extracts the remote address from the given rest request and puts in the request context. This will
|
||||
* then be copied to the subsequent action requests.
|
||||
*/
|
||||
public static void process(RestRequest request) {
|
||||
request.putInContext(KEY, request.getRemoteAddress());
|
||||
public static void process(RestRequest request, ThreadContext threadContext) {
|
||||
threadContext.putTransient(KEY, request.getRemoteAddress());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the rest remote address from the message context. If not found, returns {@code null}. transport
|
||||
* messages that were created by rest handlers, should have this in their context.
|
||||
*/
|
||||
public static InetSocketAddress restRemoteAddress(TransportMessage message) {
|
||||
SocketAddress address = message.getFromContext(KEY);
|
||||
public static InetSocketAddress restRemoteAddress(ThreadContext threadContext) {
|
||||
SocketAddress address = threadContext.getTransient(KEY);
|
||||
if (address != null && address instanceof InetSocketAddress) {
|
||||
return (InetSocketAddress) address;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void putRestRemoteAddress(TransportMessage message, SocketAddress address) {
|
||||
message.putInContext(KEY, address);
|
||||
public static void putRestRemoteAddress(ThreadContext threadContext, SocketAddress address) {
|
||||
threadContext.putTransient(KEY, address);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.elasticsearch.common.inject.Inject;
|
|||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.http.netty.NettyHttpRequest;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
|
@ -21,6 +22,7 @@ import org.elasticsearch.shield.authc.pki.PkiRealm;
|
|||
import org.elasticsearch.shield.license.ShieldLicenseState;
|
||||
import org.elasticsearch.shield.transport.SSLClientAuth;
|
||||
import org.elasticsearch.shield.transport.netty.ShieldNettyHttpServerTransport;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.jboss.netty.handler.ssl.SslHandler;
|
||||
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
|
@ -36,12 +38,15 @@ public class ShieldRestFilter extends RestFilter {
|
|||
private final AuthenticationService service;
|
||||
private final ESLogger logger;
|
||||
private final ShieldLicenseState licenseState;
|
||||
private final ThreadContext threadContext;
|
||||
private final boolean extractClientCertificate;
|
||||
|
||||
@Inject
|
||||
public ShieldRestFilter(AuthenticationService service, RestController controller, Settings settings, ShieldLicenseState licenseState) {
|
||||
public ShieldRestFilter(AuthenticationService service, RestController controller, Settings settings,
|
||||
ThreadPool threadPool, ShieldLicenseState licenseState) {
|
||||
this.service = service;
|
||||
this.licenseState = licenseState;
|
||||
this.threadContext = threadPool.getThreadContext();
|
||||
controller.registerFilter(this);
|
||||
boolean ssl = settings.getAsBoolean(ShieldNettyHttpServerTransport.HTTP_SSL_SETTING, ShieldNettyHttpServerTransport.HTTP_SSL_DEFAULT);
|
||||
extractClientCertificate = ssl && SSLClientAuth.parse(settings.get(ShieldNettyHttpServerTransport.HTTP_CLIENT_AUTH_SETTING), ShieldNettyHttpServerTransport.HTTP_CLIENT_AUTH_DEFAULT).enabled();
|
||||
|
@ -60,18 +65,18 @@ public class ShieldRestFilter extends RestFilter {
|
|||
// CORS - allow for preflight unauthenticated OPTIONS request
|
||||
if (request.method() != RestRequest.Method.OPTIONS) {
|
||||
if (extractClientCertificate) {
|
||||
putClientCertificateInContext(request, logger);
|
||||
putClientCertificateInContext(request, threadContext, logger);
|
||||
}
|
||||
service.authenticate(request);
|
||||
}
|
||||
|
||||
RemoteHostHeader.process(request);
|
||||
RemoteHostHeader.process(request, threadContext);
|
||||
}
|
||||
|
||||
filterChain.continueProcessing(request, channel);
|
||||
}
|
||||
|
||||
static void putClientCertificateInContext(RestRequest request, ESLogger logger) throws Exception {
|
||||
static void putClientCertificateInContext(RestRequest request, ThreadContext threadContext, ESLogger logger) throws Exception {
|
||||
assert request instanceof NettyHttpRequest;
|
||||
NettyHttpRequest nettyHttpRequest = (NettyHttpRequest) request;
|
||||
|
||||
|
@ -80,7 +85,7 @@ public class ShieldRestFilter extends RestFilter {
|
|||
try {
|
||||
Certificate[] certs = handler.getEngine().getSession().getPeerCertificates();
|
||||
if (certs instanceof X509Certificate[]) {
|
||||
request.putInContext(PkiRealm.PKI_CERT_HEADER_NAME, certs);
|
||||
threadContext.putTransient(PkiRealm.PKI_CERT_HEADER_NAME, certs);
|
||||
}
|
||||
} catch (SSLPeerUnverifiedException e) {
|
||||
// this happens when we only request client authentication and the client does not provide it
|
||||
|
|
|
@ -27,7 +27,7 @@ public class RestAuthenticateAction extends BaseRestHandler {
|
|||
private final AuthenticationService authenticationService;
|
||||
@Inject
|
||||
public RestAuthenticateAction(Settings settings, RestController controller, Client client, AuthenticationService authenticationService) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
this.authenticationService = authenticationService;
|
||||
controller.registerHandler(GET, "/_shield/authenticate", this);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class RestShieldInfoAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestShieldInfoAction(Settings settings, RestController controller, Client client, ClusterName clusterName, @Nullable ShieldLicenseState licenseState) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
this.clusterName = clusterName;
|
||||
this.shieldLicenseState = licenseState;
|
||||
this.shieldEnabled = ShieldPlugin.shieldEnabled(settings);
|
||||
|
|
|
@ -28,7 +28,7 @@ public class RestClearRealmCacheAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestClearRealmCacheAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
controller.registerHandler(POST, "/_shield/realm/{realms}/_cache/clear", this);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public class RestClearRolesCacheAction extends BaseRestHandler {
|
|||
|
||||
@Inject
|
||||
public RestClearRolesCacheAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
super(settings, client);
|
||||
controller.registerHandler(POST, "/_shield/roles/{roles}/_cache/clear", this);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionRequestBuilder;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.FilterClient;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.authc.AuthenticationService;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A client that takes a user and attaches it to all requests
|
||||
*/
|
||||
public class ClientWithUser extends FilterClient {
|
||||
|
||||
private final AuthenticationService authenticationService;
|
||||
private final User user;
|
||||
|
||||
/**
|
||||
* Creates a new client that will attach the user to each request.
|
||||
*
|
||||
* @param in the client to delegate to
|
||||
* @param authenticationService the authentication service that will be used for attaching the user
|
||||
* @param user the user to attach to each request
|
||||
* @see #in()
|
||||
*/
|
||||
public ClientWithUser(Client in, AuthenticationService authenticationService, User user) {
|
||||
super(in);
|
||||
this.authenticationService = authenticationService;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <Request extends ActionRequest<Request>, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void doExecute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) {
|
||||
try (ThreadContext.StoredContext ctx = threadPool().getThreadContext().stashContext()) {
|
||||
try {
|
||||
authenticationService.attachUserHeaderIfMissing(user);
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("failed to set user [{}]", e, user.principal());
|
||||
}
|
||||
super.doExecute(action, request, listener);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,7 +56,7 @@ public interface ClientTransportFilter {
|
|||
the system user will be attached. There cannot be a request outgoing from this
|
||||
node that is not associated with a user.
|
||||
*/
|
||||
authcService.attachUserHeaderIfMissing(request, User.SYSTEM);
|
||||
authcService.attachUserHeaderIfMissing(User.SYSTEM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.shield.transport;
|
|||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.action.ShieldActionMapper;
|
||||
import org.elasticsearch.shield.authc.AuthenticationService;
|
||||
|
@ -51,12 +52,15 @@ public interface ServerTransportFilter {
|
|||
private final AuthenticationService authcService;
|
||||
private final AuthorizationService authzService;
|
||||
private final ShieldActionMapper actionMapper;
|
||||
private final ThreadContext threadContext;
|
||||
private final boolean extractClientCert;
|
||||
|
||||
public NodeProfile(AuthenticationService authcService, AuthorizationService authzService, ShieldActionMapper actionMapper, boolean extractClientCert) {
|
||||
public NodeProfile(AuthenticationService authcService, AuthorizationService authzService,
|
||||
ShieldActionMapper actionMapper, ThreadContext threadContext, boolean extractClientCert) {
|
||||
this.authcService = authcService;
|
||||
this.authzService = authzService;
|
||||
this.actionMapper = actionMapper;
|
||||
this.threadContext = threadContext;
|
||||
this.extractClientCert = extractClientCert;
|
||||
}
|
||||
|
||||
|
@ -78,14 +82,14 @@ public interface ServerTransportFilter {
|
|||
}
|
||||
|
||||
if (extractClientCert && (unwrappedChannel instanceof NettyTransportChannel)) {
|
||||
Channel channel = ((NettyTransportChannel)unwrappedChannel).getChannel();
|
||||
Channel channel = ((NettyTransportChannel) unwrappedChannel).getChannel();
|
||||
SslHandler sslHandler = channel.getPipeline().get(SslHandler.class);
|
||||
assert sslHandler != null;
|
||||
|
||||
try {
|
||||
Certificate[] certs = sslHandler.getEngine().getSession().getPeerCertificates();
|
||||
if (certs instanceof X509Certificate[]) {
|
||||
request.putInContext(PkiRealm.PKI_CERT_HEADER_NAME, certs);
|
||||
threadContext.putTransient(PkiRealm.PKI_CERT_HEADER_NAME, certs);
|
||||
}
|
||||
} catch (SSLPeerUnverifiedException e) {
|
||||
// this happens when we only request client authentication and the client does not provide it
|
||||
|
@ -110,8 +114,9 @@ public interface ServerTransportFilter {
|
|||
*/
|
||||
class ClientProfile extends NodeProfile {
|
||||
|
||||
public ClientProfile(AuthenticationService authcService, AuthorizationService authzService, ShieldActionMapper actionMapper, boolean extractClientCert) {
|
||||
super(authcService, authzService, actionMapper, extractClientCert);
|
||||
public ClientProfile(AuthenticationService authcService, AuthorizationService authzService,
|
||||
ShieldActionMapper actionMapper, ThreadContext threadContext, boolean extractClientCert) {
|
||||
super(authcService, authzService, actionMapper, threadContext, extractClientCert);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,11 +8,14 @@ package org.elasticsearch.shield.transport;
|
|||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.action.ShieldActionMapper;
|
||||
import org.elasticsearch.shield.authc.AuthenticationService;
|
||||
import org.elasticsearch.shield.authz.AuthorizationService;
|
||||
import org.elasticsearch.shield.authz.accesscontrol.RequestContext;
|
||||
import org.elasticsearch.shield.license.ShieldLicenseState;
|
||||
import org.elasticsearch.shield.support.AutomatonPredicate;
|
||||
import org.elasticsearch.shield.support.Automatons;
|
||||
import org.elasticsearch.shield.transport.netty.ShieldNettyTransport;
|
||||
import org.elasticsearch.tasks.Task;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
@ -30,6 +33,7 @@ import org.elasticsearch.transport.netty.NettyTransport;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.elasticsearch.shield.transport.netty.ShieldNettyTransport.TRANSPORT_CLIENT_AUTH_DEFAULT;
|
||||
|
@ -45,6 +49,8 @@ import static org.elasticsearch.shield.transport.netty.ShieldNettyTransport.TRAN
|
|||
public class ShieldServerTransportService extends TransportService {
|
||||
|
||||
public static final String SETTING_NAME = "shield.type";
|
||||
// FIXME clean up this hack
|
||||
static final Predicate<String> INTERNAL_PREDICATE = new AutomatonPredicate(Automatons.patterns("internal:*"));
|
||||
|
||||
protected final AuthenticationService authcService;
|
||||
protected final AuthorizationService authzService;
|
||||
|
@ -72,29 +78,46 @@ public class ShieldServerTransportService extends TransportService {
|
|||
|
||||
@Override
|
||||
public <T extends TransportResponse> void sendRequest(DiscoveryNode node, String action, TransportRequest request, TransportRequestOptions options, TransportResponseHandler<T> handler) {
|
||||
try {
|
||||
clientFilter.outbound(action, request);
|
||||
super.sendRequest(node, action, request, options, handler);
|
||||
} catch (Throwable t) {
|
||||
handler.handleException(new TransportException("failed sending request", t));
|
||||
try (ThreadContext.StoredContext original = threadPool.getThreadContext().newStoredContext()) {
|
||||
// FIXME this is really just a hack. What happens is that we send a request and we always copy headers over
|
||||
// Sometimes a system action gets executed like a internal create index request or update mappings request
|
||||
// which means that the user is copied over to system actions and these really fail for internal things...
|
||||
if ((clientFilter instanceof ClientTransportFilter.Node) && INTERNAL_PREDICATE.test(action)) {
|
||||
try (ThreadContext.StoredContext ctx = threadPool.getThreadContext().stashContext()) {
|
||||
try {
|
||||
clientFilter.outbound(action, request);
|
||||
super.sendRequest(node, action, request, options, handler);
|
||||
} catch (Throwable t) {
|
||||
handler.handleException(new TransportException("failed sending request", t));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
clientFilter.outbound(action, request);
|
||||
super.sendRequest(node, action, request, options, handler);
|
||||
} catch (Throwable t) {
|
||||
handler.handleException(new TransportException("failed sending request", t));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <Request extends TransportRequest> void registerRequestHandler(String action, Supplier<Request> requestFactory, String executor, TransportRequestHandler<Request> handler) {
|
||||
TransportRequestHandler<Request> wrappedHandler = new ProfileSecuredRequestHandler<>(action, handler, profileFilters, licenseState);
|
||||
TransportRequestHandler<Request> wrappedHandler = new ProfileSecuredRequestHandler<>(action, handler, profileFilters, licenseState, threadPool.getThreadContext());
|
||||
super.registerRequestHandler(action, requestFactory, executor, wrappedHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <Request extends TransportRequest> void registerRequestHandler(String action, Supplier<Request> request, String executor, boolean forceExecution, TransportRequestHandler<Request> handler) {
|
||||
TransportRequestHandler<Request> wrappedHandler = new ProfileSecuredRequestHandler<>(action, handler, profileFilters, licenseState);
|
||||
TransportRequestHandler<Request> wrappedHandler = new ProfileSecuredRequestHandler<>(action, handler, profileFilters, licenseState, threadPool.getThreadContext());
|
||||
super.registerRequestHandler(action, request, executor, forceExecution, wrappedHandler);
|
||||
}
|
||||
|
||||
protected Map<String, ServerTransportFilter> initializeProfileFilters() {
|
||||
if (!(transport instanceof ShieldNettyTransport)) {
|
||||
return Collections.<String, ServerTransportFilter>singletonMap(NettyTransport.DEFAULT_PROFILE, new ServerTransportFilter.NodeProfile(authcService, authzService, actionMapper, false));
|
||||
return Collections.<String, ServerTransportFilter>singletonMap(NettyTransport.DEFAULT_PROFILE,
|
||||
new ServerTransportFilter.NodeProfile(authcService, authzService, actionMapper, threadPool.getThreadContext(), false));
|
||||
}
|
||||
|
||||
Map<String, Settings> profileSettingsMap = settings.getGroups("transport.profiles.", true);
|
||||
|
@ -108,10 +131,10 @@ public class ShieldServerTransportService extends TransportService {
|
|||
String type = entry.getValue().get(SETTING_NAME, "node");
|
||||
switch (type) {
|
||||
case "client":
|
||||
profileFilters.put(entry.getKey(), new ServerTransportFilter.ClientProfile(authcService, authzService, actionMapper, extractClientCert));
|
||||
profileFilters.put(entry.getKey(), new ServerTransportFilter.ClientProfile(authcService, authzService, actionMapper, threadPool.getThreadContext(), extractClientCert));
|
||||
break;
|
||||
default:
|
||||
profileFilters.put(entry.getKey(), new ServerTransportFilter.NodeProfile(authcService, authzService, actionMapper, extractClientCert));
|
||||
profileFilters.put(entry.getKey(), new ServerTransportFilter.NodeProfile(authcService, authzService, actionMapper, threadPool.getThreadContext(), extractClientCert));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +142,7 @@ public class ShieldServerTransportService extends TransportService {
|
|||
final boolean profileSsl = settings.getAsBoolean(TRANSPORT_SSL_SETTING, TRANSPORT_SSL_DEFAULT);
|
||||
final boolean clientAuth = SSLClientAuth.parse(settings.get(TRANSPORT_CLIENT_AUTH_SETTING), TRANSPORT_CLIENT_AUTH_DEFAULT).enabled();
|
||||
final boolean extractClientCert = profileSsl && clientAuth;
|
||||
profileFilters.put(NettyTransport.DEFAULT_PROFILE, new ServerTransportFilter.NodeProfile(authcService, authzService, actionMapper, extractClientCert));
|
||||
profileFilters.put(NettyTransport.DEFAULT_PROFILE, new ServerTransportFilter.NodeProfile(authcService, authzService, actionMapper, threadPool.getThreadContext(), extractClientCert));
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(profileFilters);
|
||||
|
@ -135,17 +158,20 @@ public class ShieldServerTransportService extends TransportService {
|
|||
protected final TransportRequestHandler<T> handler;
|
||||
private final Map<String, ServerTransportFilter> profileFilters;
|
||||
private final ShieldLicenseState licenseState;
|
||||
private final ThreadContext threadContext;
|
||||
|
||||
public ProfileSecuredRequestHandler(String action, TransportRequestHandler<T> handler, Map<String, ServerTransportFilter> profileFilters, ShieldLicenseState licenseState) {
|
||||
public ProfileSecuredRequestHandler(String action, TransportRequestHandler<T> handler, Map<String, ServerTransportFilter> profileFilters,
|
||||
ShieldLicenseState licenseState, ThreadContext threadContext) {
|
||||
this.action = action;
|
||||
this.handler = handler;
|
||||
this.profileFilters = profileFilters;
|
||||
this.licenseState = licenseState;
|
||||
this.threadContext = threadContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(T request, TransportChannel channel, Task task) throws Exception {
|
||||
try {
|
||||
try (ThreadContext.StoredContext ctx = threadContext.newStoredContext()) {
|
||||
if (licenseState.securityEnabled()) {
|
||||
String profile = channel.getProfileName();
|
||||
ServerTransportFilter filter = profileFilters.get(profile);
|
||||
|
@ -161,7 +187,8 @@ public class ShieldServerTransportService extends TransportService {
|
|||
assert filter != null;
|
||||
filter.inbound(action, request, channel);
|
||||
}
|
||||
RequestContext context = new RequestContext(request);
|
||||
// FIXME we should remove the RequestContext completely since we have ThreadContext but cannot yet due to the query cache
|
||||
RequestContext context = new RequestContext(request, threadContext);
|
||||
RequestContext.setCurrent(context);
|
||||
handler.messageReceived(request, channel, task);
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.elasticsearch.http.netty.NettyHttpServerTransport;
|
|||
import org.elasticsearch.shield.ssl.ServerSSLService;
|
||||
import org.elasticsearch.shield.transport.SSLClientAuth;
|
||||
import org.elasticsearch.shield.transport.filter.IPFilter;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
|
@ -40,8 +41,8 @@ public class ShieldNettyHttpServerTransport extends NettyHttpServerTransport {
|
|||
|
||||
@Inject
|
||||
public ShieldNettyHttpServerTransport(Settings settings, NetworkService networkService, BigArrays bigArrays,
|
||||
IPFilter ipFilter, ServerSSLService sslService) {
|
||||
super(settings, networkService, bigArrays);
|
||||
IPFilter ipFilter, ServerSSLService sslService, ThreadPool threadPool) {
|
||||
super(settings, networkService, bigArrays, threadPool);
|
||||
this.ipFilter = ipFilter;
|
||||
this.ssl = settings.getAsBoolean(HTTP_SSL_SETTING, HTTP_SSL_DEFAULT);
|
||||
this.sslService = sslService;
|
||||
|
@ -89,7 +90,7 @@ public class ShieldNettyHttpServerTransport extends NettyHttpServerTransport {
|
|||
private final SSLClientAuth clientAuth;
|
||||
|
||||
public HttpSslChannelPipelineFactory(NettyHttpServerTransport transport) {
|
||||
super(transport, detailedErrorsEnabled);
|
||||
super(transport, detailedErrorsEnabled, threadPool.getThreadContext());
|
||||
clientAuth = SSLClientAuth.parse(settings.get(HTTP_CLIENT_AUTH_SETTING), HTTP_CLIENT_AUTH_DEFAULT);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ public class BulkUpdateTests extends ShieldIntegTestCase {
|
|||
public void testThatBulkUpdateDoesNotLoseFields() {
|
||||
assertThat(client().prepareIndex("index1", "type").setSource("{\"test\": \"test\"}").setId("1").get().isCreated(), is(true));
|
||||
GetResponse getResponse = internalCluster().transportClient().prepareGet("index1", "type", "1").setFields("test").get();
|
||||
assertThat((String) getResponse.getField("test").getValue(), equalTo("test"));
|
||||
assertThat(getResponse.getField("test").getValue(), equalTo("test"));
|
||||
|
||||
if (randomBoolean()) {
|
||||
flushAndRefresh();
|
||||
|
|
|
@ -140,11 +140,11 @@ public class ClearRealmsCacheTests extends ShieldIntegTestCase {
|
|||
public abstract void executeRequest() throws Exception;
|
||||
|
||||
static void executeTransportRequest(ClearRealmCacheRequest request) throws Exception {
|
||||
ShieldClient client = new ShieldClient(client());
|
||||
ShieldClient shieldClient = new ShieldClient(client());
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
final AtomicReference<Throwable> error = new AtomicReference<>();
|
||||
client.clearRealmCache(request, new ActionListener<ClearRealmCacheResponse>() {
|
||||
shieldClient.clearRealmCache(request, new ActionListener<ClearRealmCacheResponse>() {
|
||||
@Override
|
||||
public void onResponse(ClearRealmCacheResponse response) {
|
||||
assertThat(response.getNodes().length, equalTo(internalCluster().getNodeNames().length));
|
||||
|
|
|
@ -13,6 +13,8 @@ import org.elasticsearch.shield.authc.support.Hasher;
|
|||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.BASIC_AUTH_HEADER;
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
|
@ -88,16 +90,16 @@ public class DocumentAndFieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.setRefresh(true)
|
||||
.get();
|
||||
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHits(response, "1");
|
||||
assertThat(response.getHits().getAt(0).getSource().size(), equalTo(1));
|
||||
assertThat(response.getHits().getAt(0).getSource().get("field1").toString(), equalTo("value1"));
|
||||
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHits(response, "2");
|
||||
|
@ -120,15 +122,15 @@ public class DocumentAndFieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
// Both users have the same role query, but user3 has access to field2 and not field1, which should result in zero hits:
|
||||
int max = scaledRandomIntBetween(4, 32);
|
||||
for (int i = 0; i < max; i++) {
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().size(), equalTo(1));
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().get("field1"), equalTo("value1"));
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("2"));
|
||||
|
@ -137,8 +139,8 @@ public class DocumentAndFieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
|
||||
// this is a bit weird the document level permission (all docs with field2:value2) don't match with the field level permissions (field1),
|
||||
// this results in document 2 being returned but no fields are visible:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("2"));
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.shield.authc.support.SecuredString;
|
|||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.BASIC_AUTH_HEADER;
|
||||
|
@ -93,8 +94,8 @@ public class DocumentLevelSecurityRandomTests extends ShieldIntegTestCase {
|
|||
builder.get();
|
||||
|
||||
for (int roleI = 1; roleI <= numberOfRoles; roleI++) {
|
||||
SearchResponse searchResponse1 = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user" + roleI, USERS_PASSWD))
|
||||
SearchResponse searchResponse1 = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user" + roleI, USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.get();
|
||||
SearchResponse searchResponse2 = client().prepareSearch("alias" + roleI).get();
|
||||
assertThat(searchResponse1.getHits().getTotalHits(), equalTo(searchResponse2.getHits().getTotalHits()));
|
||||
|
|
|
@ -29,6 +29,8 @@ import org.elasticsearch.shield.authc.support.Hasher;
|
|||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasChildQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasParentQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
|
@ -100,14 +102,14 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.setRefresh(true)
|
||||
.get();
|
||||
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(randomBoolean() ? QueryBuilders.termQuery("field1", "value1") : QueryBuilders.matchAllQuery())
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHits(response, "1");
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(randomBoolean() ? QueryBuilders.termQuery("field2", "value2") : QueryBuilders.matchAllQuery())
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
|
@ -125,31 +127,31 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
Boolean realtime = randomFrom(true, false, null);
|
||||
GetResponse response = client().prepareGet("test", "type1", "1")
|
||||
GetResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareGet("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
assertThat(response.getId(), equalTo("1"));
|
||||
response = client().prepareGet("test", "type1", "2")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareGet("test", "type1", "2")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
assertThat(response.getId(), equalTo("2"));
|
||||
|
||||
response = client().prepareGet("test", "type1", "1")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareGet("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(false));
|
||||
response = client().prepareGet("test", "type1", "2")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareGet("test", "type1", "2")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(false));
|
||||
}
|
||||
|
@ -165,40 +167,40 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
Boolean realtime = randomFrom(true, false, null);
|
||||
MultiGetResponse response = client().prepareMultiGet()
|
||||
MultiGetResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareMultiGet()
|
||||
.add("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses()[0].isFailed(), is(false));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
assertThat(response.getResponses()[0].getResponse().getId(), equalTo("1"));
|
||||
|
||||
response = client().prepareMultiGet()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareMultiGet()
|
||||
.add("test", "type1", "2")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses()[0].isFailed(), is(false));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
assertThat(response.getResponses()[0].getResponse().getId(), equalTo("2"));
|
||||
|
||||
response = client().prepareMultiGet()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareMultiGet()
|
||||
.add("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses()[0].isFailed(), is(false));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(false));
|
||||
|
||||
response = client().prepareMultiGet()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareMultiGet()
|
||||
.add("test", "type1", "2")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses()[0].isFailed(), is(false));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(false));
|
||||
|
@ -216,29 +218,29 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
Boolean realtime = randomFrom(true, false, null);
|
||||
TermVectorsResponse response = client().prepareTermVectors("test", "type1", "1")
|
||||
TermVectorsResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareTermVectors("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
assertThat(response.getId(), is("1"));
|
||||
|
||||
response = client().prepareTermVectors("test", "type1", "2")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareTermVectors("test", "type1", "2")
|
||||
.setRealtime(realtime)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
assertThat(response.getId(), is("2"));
|
||||
|
||||
response = client().prepareTermVectors("test", "type1", "1")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareTermVectors("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(false));
|
||||
|
||||
response = client().prepareTermVectors("test", "type1", "2")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareTermVectors("test", "type1", "2")
|
||||
.setRealtime(realtime)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(false));
|
||||
}
|
||||
|
@ -255,32 +257,32 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
Boolean realtime = randomFrom(true, false, null);
|
||||
MultiTermVectorsResponse response = client().prepareMultiTermVectors()
|
||||
MultiTermVectorsResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareMultiTermVectors()
|
||||
.add(new TermVectorsRequest("test", "type1", "1").realtime(realtime))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses().length, equalTo(1));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
assertThat(response.getResponses()[0].getResponse().getId(), is("1"));
|
||||
|
||||
response = client().prepareMultiTermVectors()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareMultiTermVectors()
|
||||
.add(new TermVectorsRequest("test", "type1", "2").realtime(realtime))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses().length, equalTo(1));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
assertThat(response.getResponses()[0].getResponse().getId(), is("2"));
|
||||
|
||||
response = client().prepareMultiTermVectors()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareMultiTermVectors()
|
||||
.add(new TermVectorsRequest("test", "type1", "1").realtime(realtime))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses().length, equalTo(1));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(false));
|
||||
|
||||
response = client().prepareMultiTermVectors()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareMultiTermVectors()
|
||||
.add(new TermVectorsRequest("test", "type1", "2").realtime(realtime))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses().length, equalTo(1));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(false));
|
||||
|
@ -309,9 +311,9 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
assertThat(termsAgg.getBuckets().get(0).getKeyAsString(), equalTo("value2"));
|
||||
assertThat(termsAgg.getBuckets().get(0).getDocCount(), equalTo(1l));
|
||||
|
||||
response = client().prepareSearch("test")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addAggregation(AggregationBuilders.global("global").subAggregation(AggregationBuilders.terms("field2").field("field2")))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHits(response, "1");
|
||||
|
@ -349,11 +351,11 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
assertThat(termsAgg.getBuckets().get(0).getKeyAsString(), equalTo("value3"));
|
||||
assertThat(termsAgg.getBuckets().get(0).getDocCount(), equalTo(1l));
|
||||
|
||||
response = client().prepareSearch("test")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setTypes("type1")
|
||||
.addAggregation(AggregationBuilders.children("children").childType("type2")
|
||||
.subAggregation(AggregationBuilders.terms("field3").field("field3")))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHits(response, "1");
|
||||
|
@ -392,27 +394,27 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
assertThat(searchResponse.getHits().getAt(1).id(), equalTo("c2"));
|
||||
|
||||
// Both user1 and user2 can't see field1 and field2, no parent/child query should yield results:
|
||||
searchResponse = client().prepareSearch("test")
|
||||
searchResponse = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(hasChildQuery("child", matchAllQuery()))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 0l);
|
||||
|
||||
searchResponse = client().prepareSearch("test")
|
||||
searchResponse = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(hasChildQuery("child", matchAllQuery()))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 0l);
|
||||
|
||||
searchResponse = client().prepareSearch("test")
|
||||
searchResponse = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(hasParentQuery("parent", matchAllQuery()))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 0l);
|
||||
|
||||
searchResponse = client().prepareSearch("test")
|
||||
searchResponse = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(hasParentQuery("parent", matchAllQuery()))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 0l);
|
||||
}
|
||||
|
@ -427,30 +429,30 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
// Percolator without a query just evaluates all percolator queries that are loaded, so we have a match:
|
||||
PercolateResponse response = client().preparePercolate()
|
||||
PercolateResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.preparePercolate()
|
||||
.setDocumentType("type")
|
||||
.setPercolateDoc(new PercolateSourceBuilder.DocBuilder().setDoc("{}"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getCount(), equalTo(1l));
|
||||
assertThat(response.getMatches()[0].getId().string(), equalTo("1"));
|
||||
|
||||
// Percolator with a query on a document that the current user can see. Percolator will have one query to evaluate, so there is a match:
|
||||
response = client().preparePercolate()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.preparePercolate()
|
||||
.setDocumentType("type")
|
||||
.setPercolateQuery(termQuery("field1", "value1"))
|
||||
.setPercolateDoc(new PercolateSourceBuilder.DocBuilder().setDoc("{}"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getCount(), equalTo(1l));
|
||||
assertThat(response.getMatches()[0].getId().string(), equalTo("1"));
|
||||
|
||||
// Percolator with a query on a document that the current user can't see. Percolator will not have queries to evaluate, so there is no match:
|
||||
response = client().preparePercolate()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.preparePercolate()
|
||||
.setDocumentType("type")
|
||||
.setPercolateQuery(termQuery("field1", "value1"))
|
||||
.setPercolateDoc(new PercolateSourceBuilder.DocBuilder().setDoc("{}"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getCount(), equalTo(0l));
|
||||
|
||||
|
@ -459,10 +461,10 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
ensureGreen("test");
|
||||
|
||||
// Ensure that the query loading that happens at startup has permissions to load the percolator queries:
|
||||
response = client().preparePercolate()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.preparePercolate()
|
||||
.setDocumentType("type")
|
||||
.setPercolateDoc(new PercolateSourceBuilder.DocBuilder().setDoc("{}"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getCount(), equalTo(1l));
|
||||
assertThat(response.getMatches()[0].getId().string(), equalTo("1"));
|
||||
|
@ -482,19 +484,19 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
int max = scaledRandomIntBetween(4, 32);
|
||||
for (int i = 0; i < max; i++) {
|
||||
Boolean requestCache = randomFrom(true, null);
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setSize(0)
|
||||
.setQuery(termQuery("field1", "value1"))
|
||||
.setRequestCache(requestCache)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
response = client().prepareSearch("test")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setSize(0)
|
||||
.setQuery(termQuery("field1", "value1"))
|
||||
.setRequestCache(requestCache)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 0);
|
||||
|
@ -511,8 +513,8 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
|
||||
// With document level security enabled the update is not allowed:
|
||||
try {
|
||||
client().prepareUpdate("test", "type", "1").setDoc("field1", "value2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareUpdate("test", "type", "1").setDoc("field1", "value2")
|
||||
.get();
|
||||
fail("failed, because update request shouldn't be allowed if document level security is enabled");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
|
@ -528,8 +530,8 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
|||
|
||||
// With document level security enabled the update in bulk is not allowed:
|
||||
try {
|
||||
client().prepareBulk()
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareBulk()
|
||||
.add(new UpdateRequest("test", "type", "1").doc("field1", "value3"))
|
||||
.get();
|
||||
fail("failed, because bulk request with updates shouldn't be allowed if field or document level security is enabled");
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.shield.authc.support.SecuredString;
|
|||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -135,17 +136,17 @@ public class FieldLevelSecurityRandomTests extends ShieldIntegTestCase {
|
|||
|
||||
for (String allowedField : allowedFields) {
|
||||
logger.info("Checking allowed field [{}]", allowedField);
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery(allowedField, "value"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
}
|
||||
for (String disallowedField : disAllowedFields) {
|
||||
logger.info("Checking disallowed field [{}]", disallowedField);
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery(disallowedField, "value"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(response, 0);
|
||||
}
|
||||
|
@ -165,8 +166,8 @@ public class FieldLevelSecurityRandomTests extends ShieldIntegTestCase {
|
|||
}
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse actual = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
SearchResponse actual = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addSort("_uid", SortOrder.ASC)
|
||||
.setQuery(QueryBuilders.boolQuery()
|
||||
.should(QueryBuilders.termQuery("field1", "value"))
|
||||
|
@ -186,8 +187,8 @@ public class FieldLevelSecurityRandomTests extends ShieldIntegTestCase {
|
|||
assertThat(actual.getHits().getAt(i).getId(), equalTo(expected.getHits().getAt(i).getId()));
|
||||
}
|
||||
|
||||
actual = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD))
|
||||
actual = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addSort("_uid", SortOrder.ASC)
|
||||
.setQuery(QueryBuilders.boolQuery()
|
||||
.should(QueryBuilders.termQuery("field1", "value"))
|
||||
|
@ -207,8 +208,8 @@ public class FieldLevelSecurityRandomTests extends ShieldIntegTestCase {
|
|||
assertThat(actual.getHits().getAt(i).getId(), equalTo(expected.getHits().getAt(i).getId()));
|
||||
}
|
||||
|
||||
actual = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD))
|
||||
actual = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addSort("_uid", SortOrder.ASC)
|
||||
.setQuery(QueryBuilders.boolQuery()
|
||||
.should(QueryBuilders.termQuery("field1", "value"))
|
||||
|
|
|
@ -29,6 +29,8 @@ import org.elasticsearch.shield.authc.support.SecuredString;
|
|||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasChildQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
|
||||
|
@ -127,63 +129,63 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
// user1 has access to field1, so the query should match with the document:
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field1", "value1"))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
// user2 has no access to field1, so the query should not match with the document:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field1", "value1"))
|
||||
.get();
|
||||
assertHitCount(response, 0);
|
||||
// user3 has access to field1 and field2, so the query should match with the document:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field1", "value1"))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
// user4 has access to no fields, so the query should not match with the document:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field1", "value1"))
|
||||
.get();
|
||||
assertHitCount(response, 0);
|
||||
// user5 has no field level security configured, so the query should match with the document:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field1", "value1"))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
|
||||
// user1 has no access to field1, so the query should not match with the document:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field2", "value2"))
|
||||
.get();
|
||||
assertHitCount(response, 0);
|
||||
// user2 has access to field1, so the query should match with the document:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field2", "value2"))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
// user3 has access to field1 and field2, so the query should match with the document:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field2", "value2"))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
// user4 has access to no fields, so the query should not match with the document:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field2", "value2"))
|
||||
.get();
|
||||
assertHitCount(response, 0);
|
||||
// user5 has no field level security configured, so the query should match with the document:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field2", "value2"))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
|
@ -199,30 +201,30 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
|
||||
Boolean realtime = randomFrom(true, false, null);
|
||||
// user1 is granted access to field1 only:
|
||||
GetResponse response = client().prepareGet("test", "type1", "1")
|
||||
GetResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareGet("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
assertThat(response.getSource().size(), equalTo(1));
|
||||
assertThat(response.getSource().get("field1").toString(), equalTo("value1"));
|
||||
|
||||
// user2 is granted access to field2 only:
|
||||
response = client().prepareGet("test", "type1", "1")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareGet("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
assertThat(response.getSource().size(), equalTo(1));
|
||||
assertThat(response.getSource().get("field2").toString(), equalTo("value2"));
|
||||
|
||||
// user3 is granted access to field1 and field2:
|
||||
response = client().prepareGet("test", "type1", "1")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD)))
|
||||
.prepareGet("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
assertThat(response.getSource().size(), equalTo(2));
|
||||
|
@ -230,19 +232,19 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
assertThat(response.getSource().get("field2").toString(), equalTo("value2"));
|
||||
|
||||
// user4 is granted access to no fields, so the get response does say the doc exist, but no fields are returned:
|
||||
response = client().prepareGet("test", "type1", "1")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD)))
|
||||
.prepareGet("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
assertThat(response.getSource().size(), equalTo(0));
|
||||
|
||||
// user5 has no field level security configured, so all fields are returned:
|
||||
response = client().prepareGet("test", "type1", "1")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD)))
|
||||
.prepareGet("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
assertThat(response.getSource().size(), equalTo(2));
|
||||
|
@ -259,11 +261,11 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
|
||||
Boolean realtime = randomFrom(true, false, null);
|
||||
// user1 is granted access to field1 only:
|
||||
MultiGetResponse response = client().prepareMultiGet()
|
||||
MultiGetResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareMultiGet()
|
||||
.add("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses()[0].isFailed(), is(false));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
|
@ -271,11 +273,11 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
assertThat(response.getResponses()[0].getResponse().getSource().get("field1").toString(), equalTo("value1"));
|
||||
|
||||
// user2 is granted access to field2 only:
|
||||
response = client().prepareMultiGet()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareMultiGet()
|
||||
.add("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses()[0].isFailed(), is(false));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
|
@ -283,11 +285,11 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
assertThat(response.getResponses()[0].getResponse().getSource().get("field2").toString(), equalTo("value2"));
|
||||
|
||||
// user3 is granted access to field1 and field2:
|
||||
response = client().prepareMultiGet()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD)))
|
||||
.prepareMultiGet()
|
||||
.add("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses()[0].isFailed(), is(false));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
|
@ -296,22 +298,22 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
assertThat(response.getResponses()[0].getResponse().getSource().get("field2").toString(), equalTo("value2"));
|
||||
|
||||
// user4 is granted access to no fields, so the get response does say the doc exist, but no fields are returned:
|
||||
response = client().prepareMultiGet()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD)))
|
||||
.prepareMultiGet()
|
||||
.add("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses()[0].isFailed(), is(false));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
assertThat(response.getResponses()[0].getResponse().getSource().size(), equalTo(0));
|
||||
|
||||
// user5 has no field level security configured, so all fields are returned:
|
||||
response = client().prepareMultiGet()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD)))
|
||||
.prepareMultiGet()
|
||||
.add("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.setRefresh(true)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses()[0].isFailed(), is(false));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
|
@ -329,41 +331,41 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
// user1 is granted access to field1 only:
|
||||
FieldStatsResponse response = client().prepareFieldStats()
|
||||
FieldStatsResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareFieldStats()
|
||||
.setFields("field1", "field2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getAllFieldStats().size(), equalTo(1));
|
||||
assertThat(response.getAllFieldStats().get("field1").getDocCount(), equalTo(1l));
|
||||
|
||||
// user2 is granted access to field2 only:
|
||||
response = client().prepareFieldStats()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareFieldStats()
|
||||
.setFields("field1", "field2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getAllFieldStats().size(), equalTo(1));
|
||||
assertThat(response.getAllFieldStats().get("field2").getDocCount(), equalTo(1l));
|
||||
|
||||
// user3 is granted access to field1 and field2:
|
||||
response = client().prepareFieldStats()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD)))
|
||||
.prepareFieldStats()
|
||||
.setFields("field1", "field2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getAllFieldStats().size(), equalTo(2));
|
||||
assertThat(response.getAllFieldStats().get("field1").getDocCount(), equalTo(1l));
|
||||
assertThat(response.getAllFieldStats().get("field2").getDocCount(), equalTo(1l));
|
||||
|
||||
// user4 is granted access to no fields:
|
||||
response = client().prepareFieldStats()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD)))
|
||||
.prepareFieldStats()
|
||||
.setFields("field1", "field2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getAllFieldStats().size(), equalTo(0));
|
||||
|
||||
// user5 has no field level security configured:
|
||||
response = client().prepareFieldStats()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD)))
|
||||
.prepareFieldStats()
|
||||
.setFields("field1", "field2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getAllFieldStats().size(), equalTo(2));
|
||||
assertThat(response.getAllFieldStats().get("field1").getDocCount(), equalTo(1l));
|
||||
|
@ -381,14 +383,14 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
|
||||
int max = scaledRandomIntBetween(4, 32);
|
||||
for (int i = 0; i < max; i++) {
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(constantScoreQuery(termQuery("field1", "value1")))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
response = client().prepareSearch("test")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(constantScoreQuery(termQuery("field1", "value1")))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(response, 0);
|
||||
}
|
||||
|
@ -406,19 +408,19 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
int max = scaledRandomIntBetween(4, 32);
|
||||
for (int i = 0; i < max; i++) {
|
||||
Boolean requestCache = randomFrom(true, null);
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setSize(0)
|
||||
.setQuery(termQuery("field1", "value1"))
|
||||
.setRequestCache(requestCache)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
response = client().prepareSearch("test")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setSize(0)
|
||||
.setQuery(termQuery("field1", "value1"))
|
||||
.setRequestCache(requestCache)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 0);
|
||||
|
@ -434,46 +436,46 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
// user1 is granted access to field1 only:
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addField("field1")
|
||||
.addField("field2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getHits().getAt(0).fields().size(), equalTo(1));
|
||||
assertThat(response.getHits().getAt(0).fields().get("field1").<String>getValue(), equalTo("value1"));
|
||||
|
||||
// user2 is granted access to field2 only:
|
||||
response = client().prepareSearch("test")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addField("field1")
|
||||
.addField("field2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getHits().getAt(0).fields().size(), equalTo(1));
|
||||
assertThat(response.getHits().getAt(0).fields().get("field2").<String>getValue(), equalTo("value2"));
|
||||
|
||||
// user3 is granted access to field1 and field2:
|
||||
response = client().prepareSearch("test")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addField("field1")
|
||||
.addField("field2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getHits().getAt(0).fields().size(), equalTo(2));
|
||||
assertThat(response.getHits().getAt(0).fields().get("field1").<String>getValue(), equalTo("value1"));
|
||||
assertThat(response.getHits().getAt(0).fields().get("field2").<String>getValue(), equalTo("value2"));
|
||||
|
||||
// user4 is granted access to no fields:
|
||||
response = client().prepareSearch("test")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addField("field1")
|
||||
.addField("field2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getHits().getAt(0).fields().size(), equalTo(0));
|
||||
|
||||
// user5 has no field level security configured:
|
||||
response = client().prepareSearch("test")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addField("field1")
|
||||
.addField("field2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getHits().getAt(0).fields().size(), equalTo(2));
|
||||
assertThat(response.getHits().getAt(0).fields().get("field1").<String>getValue(), equalTo("value1"));
|
||||
|
@ -489,36 +491,36 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
// user1 is granted access to field1 only:
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.get();
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().size(), equalTo(1));
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().get("field1").toString(), equalTo("value1"));
|
||||
|
||||
// user2 is granted access to field2 only:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.get();
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().size(), equalTo(1));
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().get("field2").toString(), equalTo("value2"));
|
||||
|
||||
// user3 is granted access to field1 and field2:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.get();
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().size(), equalTo(2));
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().get("field1").toString(), equalTo("value1"));
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().get("field2").toString(), equalTo("value2"));
|
||||
|
||||
// user4 is granted access to no fields:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.get();
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().size(), equalTo(0));
|
||||
|
||||
// user5 has no field level security configured:
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user5", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.get();
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().size(), equalTo(2));
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().get("field1").toString(), equalTo("value1"));
|
||||
|
@ -535,29 +537,29 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
// user1 is granted to use field1, so it is included in the sort_values
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addSort("field1", SortOrder.ASC)
|
||||
.get();
|
||||
assertThat((Long) response.getHits().getAt(0).sortValues()[0], equalTo(1l));
|
||||
|
||||
// user2 is not granted to use field1, so the default missing sort value is included
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addSort("field1", SortOrder.ASC)
|
||||
.get();
|
||||
assertThat((Long) response.getHits().getAt(0).sortValues()[0], equalTo(Long.MAX_VALUE));
|
||||
|
||||
// user1 is not granted to use field2, so the default missing sort value is included
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addSort("field2", SortOrder.ASC)
|
||||
.get();
|
||||
assertThat((Long) response.getHits().getAt(0).sortValues()[0], equalTo(Long.MAX_VALUE));
|
||||
|
||||
// user2 is granted to use field2, so it is included in the sort_values
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addSort("field2", SortOrder.ASC)
|
||||
.get();
|
||||
assertThat((Long) response.getHits().getAt(0).sortValues()[0], equalTo(2l));
|
||||
|
@ -572,29 +574,29 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
// user1 is authorized to use field1, so buckets are include for a term agg on field1
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addAggregation(AggregationBuilders.terms("_name").field("field1"))
|
||||
.get();
|
||||
assertThat(((Terms) response.getAggregations().get("_name")).getBucketByKey("value1").getDocCount(), equalTo(1l));
|
||||
|
||||
// user2 is not authorized to use field1, so no buckets are include for a term agg on field1
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addAggregation(AggregationBuilders.terms("_name").field("field1"))
|
||||
.get();
|
||||
assertThat(((Terms) response.getAggregations().get("_name")).getBucketByKey("value1"), nullValue());
|
||||
|
||||
// user1 is not authorized to use field2, so no buckets are include for a term agg on field2
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addAggregation(AggregationBuilders.terms("_name").field("field2"))
|
||||
.get();
|
||||
assertThat(((Terms) response.getAggregations().get("_name")).getBucketByKey("value2"), nullValue());
|
||||
|
||||
// user2 is authorized to use field2, so buckets are include for a term agg on field2
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.addAggregation(AggregationBuilders.terms("_name").field("field2"))
|
||||
.get();
|
||||
assertThat(((Terms) response.getAggregations().get("_name")).getBucketByKey("value2").getDocCount(), equalTo(1l));
|
||||
|
@ -609,24 +611,24 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
Boolean realtime = randomFrom(true, false, null);
|
||||
TermVectorsResponse response = client().prepareTermVectors("test", "type1", "1")
|
||||
TermVectorsResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareTermVectors("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
assertThat(response.getFields().size(), equalTo(1));
|
||||
assertThat(response.getFields().terms("field1").size(), equalTo(1l));
|
||||
|
||||
response = client().prepareTermVectors("test", "type1", "1")
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareTermVectors("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
assertThat(response.getFields().size(), equalTo(1));
|
||||
assertThat(response.getFields().terms("field2").size(), equalTo(1l));
|
||||
|
||||
response = client().prepareTermVectors("test", "type1", "1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD)))
|
||||
.prepareTermVectors("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
|
@ -634,8 +636,8 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
assertThat(response.getFields().terms("field1").size(), equalTo(1l));
|
||||
assertThat(response.getFields().terms("field2").size(), equalTo(1l));
|
||||
|
||||
response = client().prepareTermVectors("test", "type1", "1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD)))
|
||||
.prepareTermVectors("test", "type1", "1")
|
||||
.setRealtime(realtime)
|
||||
.get();
|
||||
assertThat(response.isExists(), is(true));
|
||||
|
@ -651,27 +653,27 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
Boolean realtime = randomFrom(true, false, null);
|
||||
MultiTermVectorsResponse response = client().prepareMultiTermVectors()
|
||||
MultiTermVectorsResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareMultiTermVectors()
|
||||
.add(new TermVectorsRequest("test", "type1", "1").realtime(realtime))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses().length, equalTo(1));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
assertThat(response.getResponses()[0].getResponse().getFields().size(), equalTo(1));
|
||||
assertThat(response.getResponses()[0].getResponse().getFields().terms("field1").size(), equalTo(1l));
|
||||
|
||||
response = client().prepareMultiTermVectors()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareMultiTermVectors()
|
||||
.add(new TermVectorsRequest("test", "type1", "1").realtime(realtime))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses().length, equalTo(1));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
assertThat(response.getResponses()[0].getResponse().getFields().size(), equalTo(1));
|
||||
assertThat(response.getResponses()[0].getResponse().getFields().terms("field2").size(), equalTo(1l));
|
||||
|
||||
response = client().prepareMultiTermVectors()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD)))
|
||||
.prepareMultiTermVectors()
|
||||
.add(new TermVectorsRequest("test", "type1", "1").realtime(realtime))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user3", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses().length, equalTo(1));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
|
@ -679,9 +681,9 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
assertThat(response.getResponses()[0].getResponse().getFields().terms("field1").size(), equalTo(1l));
|
||||
assertThat(response.getResponses()[0].getResponse().getFields().terms("field2").size(), equalTo(1l));
|
||||
|
||||
response = client().prepareMultiTermVectors()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD)))
|
||||
.prepareMultiTermVectors()
|
||||
.add(new TermVectorsRequest("test", "type1", "1").realtime(realtime))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user4", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getResponses().length, equalTo(1));
|
||||
assertThat(response.getResponses()[0].getResponse().isExists(), is(true));
|
||||
|
@ -698,20 +700,20 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
// Percolator without a query just evaluates all percolator queries that are loaded, so we have a match:
|
||||
PercolateResponse response = client().preparePercolate()
|
||||
PercolateResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.preparePercolate()
|
||||
.setDocumentType("type")
|
||||
.setPercolateDoc(new PercolateSourceBuilder.DocBuilder().setDoc("{}"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getCount(), equalTo(1l));
|
||||
assertThat(response.getMatches()[0].getId().string(), equalTo("1"));
|
||||
|
||||
// Percolator with a query on a field that the current user can't see. Percolator will not have queries to evaluate, so there is no match:
|
||||
response = client().preparePercolate()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.preparePercolate()
|
||||
.setDocumentType("type")
|
||||
.setPercolateQuery(termQuery("field1", "value1"))
|
||||
.setPercolateDoc(new PercolateSourceBuilder.DocBuilder().setDoc("{}"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getCount(), equalTo(0l));
|
||||
|
||||
|
@ -720,10 +722,10 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
ensureGreen("test");
|
||||
|
||||
// Ensure that the query loading that happens at startup has permissions to load the percolator queries:
|
||||
response = client().preparePercolate()
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.preparePercolate()
|
||||
.setDocumentType("type")
|
||||
.setPercolateDoc(new PercolateSourceBuilder.DocBuilder().setDoc("{}"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertThat(response.getCount(), equalTo(1l));
|
||||
assertThat(response.getMatches()[0].getId().string(), equalTo("1"));
|
||||
|
@ -741,17 +743,17 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
client().prepareIndex("test", "child", "c2").setSource("field1", "yellow").setParent("p1").get();
|
||||
refresh();
|
||||
|
||||
SearchResponse searchResponse = client().prepareSearch("test")
|
||||
SearchResponse searchResponse = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(hasChildQuery("child", termQuery("field1", "yellow")))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 1l);
|
||||
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
|
||||
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
|
||||
|
||||
searchResponse = client().prepareSearch("test")
|
||||
searchResponse = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(hasChildQuery("child", termQuery("field1", "yellow")))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user2", USERS_PASSWD))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 0l);
|
||||
}
|
||||
|
@ -767,8 +769,8 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
|
||||
// With field level security enabled the update is not allowed:
|
||||
try {
|
||||
client().prepareUpdate("test", "type", "1").setDoc("field2", "value2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareUpdate("test", "type", "1").setDoc("field2", "value2")
|
||||
.get();
|
||||
fail("failed, because update request shouldn't be allowed if field level security is enabled");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
|
@ -784,8 +786,8 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
|
||||
// With field level security enabled the update in bulk is not allowed:
|
||||
try {
|
||||
client().prepareBulk()
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareBulk()
|
||||
.add(new UpdateRequest("test", "type", "1").doc("field2", "value3"))
|
||||
.get();
|
||||
fail("failed, because bulk request with updates shouldn't be allowed if field level security is enabled");
|
||||
|
@ -810,8 +812,8 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
// user6 has access to all fields, so the query should match with the document:
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user6", USERS_PASSWD))
|
||||
SearchResponse response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user6", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field1", "value1"))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
|
@ -819,8 +821,8 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
|||
assertThat(response.getHits().getAt(0).sourceAsMap().get("field1").toString(), equalTo("value1"));
|
||||
assertThat(response.getHits().getAt(0).sourceAsMap().get("field2").toString(), equalTo("value2"));
|
||||
|
||||
response = client().prepareSearch("test")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user6", USERS_PASSWD))
|
||||
response = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user6", USERS_PASSWD)))
|
||||
.prepareSearch("test")
|
||||
.setQuery(matchQuery("field2", "value2"))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
|
|
|
@ -13,6 +13,8 @@ import org.elasticsearch.shield.authc.support.Hasher;
|
|||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.BASIC_AUTH_HEADER;
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
|
@ -72,20 +74,20 @@ public class IndicesPermissionsWithAliasesWildcardsAndRegexsTests extends Shield
|
|||
.setRefresh(true)
|
||||
.get();
|
||||
|
||||
GetResponse getResponse = client().prepareGet("test", "type1", "1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
GetResponse getResponse = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareGet("test", "type1", "1")
|
||||
.get();
|
||||
assertThat(getResponse.getSource().size(), equalTo(1));
|
||||
assertThat((String) getResponse.getSource().get("field1"), equalTo("value1"));
|
||||
|
||||
getResponse = client().prepareGet("my_alias", "type1", "1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
getResponse = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareGet("my_alias", "type1", "1")
|
||||
.get();
|
||||
assertThat(getResponse.getSource().size(), equalTo(1));
|
||||
assertThat((String) getResponse.getSource().get("field2"), equalTo("value2"));
|
||||
|
||||
getResponse = client().prepareGet("an_alias", "type1", "1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD))
|
||||
getResponse = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user1", USERS_PASSWD)))
|
||||
.prepareGet("an_alias", "type1", "1")
|
||||
.get();
|
||||
assertThat(getResponse.getSource().size(), equalTo(1));
|
||||
assertThat((String) getResponse.getSource().get("field3"), equalTo("value3"));
|
||||
|
|
|
@ -14,7 +14,6 @@ import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
|
|||
import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.support.Headers;
|
||||
import org.elasticsearch.client.transport.NoNodeAvailableException;
|
||||
import org.elasticsearch.client.transport.TransportClient;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
|
@ -24,6 +23,7 @@ import org.elasticsearch.common.inject.Inject;
|
|||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.license.core.License.OperationMode;
|
||||
import org.elasticsearch.license.plugin.LicensePlugin;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
|
@ -203,7 +203,7 @@ public class LicensingTests extends ShieldIntegTestCase {
|
|||
.put(internalCluster().transportClient().settings());
|
||||
// remove user info
|
||||
builder.remove("shield.user");
|
||||
builder.remove(Headers.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER);
|
||||
builder.remove(ThreadContext.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER);
|
||||
|
||||
// basic has no auth
|
||||
try (TransportClient client = TransportClient.builder().settings(builder).addPlugin(XPackPlugin.class).build()) {
|
||||
|
|
|
@ -13,21 +13,23 @@ import org.elasticsearch.client.Client;
|
|||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.shield.authc.support.Hasher;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
import org.elasticsearch.test.ShieldSettingsSource;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.indicesQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.BASIC_AUTH_HEADER;
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class MultipleIndicesPermissionsTests extends ShieldIntegTestCase {
|
||||
protected static final String USERS_PASSWD_HASHED = new String(Hasher.BCRYPT.hash(new SecuredString("passwd".toCharArray())));
|
||||
protected static final SecuredString PASSWD = new SecuredString("passwd".toCharArray());
|
||||
protected static final String USERS_PASSWD_HASHED = new String(Hasher.BCRYPT.hash(PASSWD));
|
||||
|
||||
@Override
|
||||
protected String configRoles() {
|
||||
|
@ -154,8 +156,8 @@ public class MultipleIndicesPermissionsTests extends ShieldIntegTestCase {
|
|||
|
||||
Client client = internalCluster().transportClient();
|
||||
|
||||
SearchResponse response = client.prepareSearch("a")
|
||||
.putHeader(BASIC_AUTH_HEADER, userHeader("user_a", "passwd"))
|
||||
SearchResponse response = client.filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user_a", PASSWD)))
|
||||
.prepareSearch("a")
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
|
@ -164,16 +166,16 @@ public class MultipleIndicesPermissionsTests extends ShieldIntegTestCase {
|
|||
new String[] { "_all"} : randomBoolean() ?
|
||||
new String[] { "*" } :
|
||||
new String[] {};
|
||||
response = client.prepareSearch(indices)
|
||||
.putHeader(BASIC_AUTH_HEADER, userHeader("user_a", "passwd"))
|
||||
response = client.filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user_a", PASSWD)))
|
||||
.prepareSearch(indices)
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
|
||||
try {
|
||||
indices = randomBoolean() ? new String[] { "a", "b" } : new String[] { "b", "a" };
|
||||
client.prepareSearch(indices)
|
||||
.putHeader(BASIC_AUTH_HEADER, userHeader("user_a", "passwd"))
|
||||
client.filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user_a", PASSWD)))
|
||||
.prepareSearch(indices)
|
||||
.get();
|
||||
fail("expected an authorization excpetion when trying to search on multiple indices where there are no search permissions on one/some of them");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
|
@ -181,15 +183,15 @@ public class MultipleIndicesPermissionsTests extends ShieldIntegTestCase {
|
|||
assertThat(e.status(), is(RestStatus.FORBIDDEN));
|
||||
}
|
||||
|
||||
response = client.prepareSearch("b")
|
||||
.putHeader(BASIC_AUTH_HEADER, userHeader("user_ab", "passwd"))
|
||||
response = client.filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user_ab", PASSWD)))
|
||||
.prepareSearch("b")
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
|
||||
indices = randomBoolean() ? new String[] { "a", "b" } : new String[] { "b", "a" };
|
||||
response = client.prepareSearch(indices)
|
||||
.putHeader(BASIC_AUTH_HEADER, userHeader("user_ab", "passwd"))
|
||||
response = client.filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user_ab", PASSWD)))
|
||||
.prepareSearch(indices)
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 2);
|
||||
|
@ -198,14 +200,10 @@ public class MultipleIndicesPermissionsTests extends ShieldIntegTestCase {
|
|||
new String[] { "_all"} : randomBoolean() ?
|
||||
new String[] { "*" } :
|
||||
new String[] {};
|
||||
response = client.prepareSearch(indices)
|
||||
.putHeader(BASIC_AUTH_HEADER, userHeader("user_ab", "passwd"))
|
||||
response = client.filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("user_ab", PASSWD)))
|
||||
.prepareSearch(indices)
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 2);
|
||||
}
|
||||
|
||||
private static String userHeader(String username, String password) {
|
||||
return UsernamePasswordToken.basicAuthHeaderValue(username, SecuredStringTests.build(password));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
|||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
|
@ -92,9 +93,9 @@ public class PermissionPrecedenceTests extends ShieldIntegTestCase {
|
|||
|
||||
// first lets try with "admin"... all should work
|
||||
|
||||
PutIndexTemplateResponse putResponse = client.admin().indices().preparePutTemplate("template1")
|
||||
PutIndexTemplateResponse putResponse = client.filterWithHeader(Collections.singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, basicAuthHeaderValue(transportClientUsername(), transportClientPassword())))
|
||||
.admin().indices().preparePutTemplate("template1")
|
||||
.setTemplate("test_*")
|
||||
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, basicAuthHeaderValue(transportClientUsername(), transportClientPassword()))
|
||||
.get();
|
||||
assertAcked(putResponse);
|
||||
|
||||
|
@ -106,9 +107,9 @@ public class PermissionPrecedenceTests extends ShieldIntegTestCase {
|
|||
// now lets try with "user"
|
||||
|
||||
try {
|
||||
client.admin().indices().preparePutTemplate("template1")
|
||||
client.filterWithHeader(Collections.singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, basicAuthHeaderValue("user", transportClientPassword())))
|
||||
.admin().indices().preparePutTemplate("template1")
|
||||
.setTemplate("test_*")
|
||||
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, basicAuthHeaderValue("user", transportClientPassword()))
|
||||
.get();
|
||||
fail("expected an authorization exception as template APIs should require cluster ALL permission");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
|
@ -117,8 +118,8 @@ public class PermissionPrecedenceTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
try {
|
||||
client.admin().indices().prepareGetTemplates("template1")
|
||||
.putHeader("Authorization", basicAuthHeaderValue("user", SecuredStringTests.build("test123")))
|
||||
client.filterWithHeader(Collections.singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, basicAuthHeaderValue("user", SecuredStringTests.build("test123"))))
|
||||
.admin().indices().prepareGetTemplates("template1")
|
||||
.get();
|
||||
fail("expected an authorization exception as template APIs should require cluster ALL permission");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
|
|
|
@ -19,6 +19,8 @@ import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
|||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.elasticsearch.client.Requests.searchRequest;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.test.ShieldTestsUtils.assertAuthorizationException;
|
||||
|
@ -77,21 +79,21 @@ public class SearchGetAndSuggestPermissionsTests extends ShieldIntegTestCase {
|
|||
|
||||
Client client = internalCluster().transportClient();
|
||||
|
||||
SuggestResponse suggestResponse = client.prepareSuggest("a")
|
||||
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("suggest_user", "passwd"))
|
||||
SuggestResponse suggestResponse = client.filterWithHeader(Collections.singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("suggest_user", "passwd")))
|
||||
.prepareSuggest("a")
|
||||
.addSuggestion(SuggestBuilders.termSuggestion("name").field("name").text("val")).get();
|
||||
assertNoFailures(suggestResponse);
|
||||
assertThat(suggestResponse.getSuggest().size(), is(1));
|
||||
|
||||
suggestResponse = client.prepareSuggest("a")
|
||||
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd"))
|
||||
suggestResponse = client.filterWithHeader(Collections.singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd")))
|
||||
.prepareSuggest("a")
|
||||
.addSuggestion(SuggestBuilders.termSuggestion("name").field("name").text("val")).get();
|
||||
assertNoFailures(suggestResponse);
|
||||
assertThat(suggestResponse.getSuggest().size(), is(1));
|
||||
|
||||
try {
|
||||
client.prepareSearch("a")
|
||||
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("suggest_user", "passwd"))
|
||||
client.filterWithHeader(Collections.singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("suggest_user", "passwd")))
|
||||
.prepareSearch("a")
|
||||
.get();
|
||||
fail("a user with only a suggest privilege cannot execute search");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
|
@ -115,8 +117,8 @@ public class SearchGetAndSuggestPermissionsTests extends ShieldIntegTestCase {
|
|||
Client client = internalCluster().transportClient();
|
||||
|
||||
try {
|
||||
client.prepareGet("a", "type", indexResponse.getId())
|
||||
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd"))
|
||||
client.filterWithHeader(Collections.singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd")))
|
||||
.prepareGet("a", "type", indexResponse.getId())
|
||||
.get();
|
||||
fail("a user with only search privilege should not be authorized for a get request");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
|
@ -140,16 +142,16 @@ public class SearchGetAndSuggestPermissionsTests extends ShieldIntegTestCase {
|
|||
|
||||
Client client = internalCluster().transportClient();
|
||||
|
||||
MultiGetResponse response = client.prepareMultiGet().add("a", "type", indexResponse.getId())
|
||||
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("get_user", "passwd"))
|
||||
MultiGetResponse response = client.filterWithHeader(Collections.singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("get_user", "passwd")))
|
||||
.prepareMultiGet().add("a", "type", indexResponse.getId())
|
||||
.get();
|
||||
assertNotNull(response);
|
||||
assertThat(response.getResponses().length, is(1));
|
||||
assertThat(response.getResponses()[0].getId(), equalTo(indexResponse.getId()));
|
||||
|
||||
try {
|
||||
client.prepareMultiGet().add("a", "type", indexResponse.getId())
|
||||
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd"))
|
||||
client.filterWithHeader(Collections.singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd")))
|
||||
.prepareMultiGet().add("a", "type", indexResponse.getId())
|
||||
.get();
|
||||
fail("a user with only a search privilege should not be able to execute the mget API");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
|
@ -173,8 +175,8 @@ public class SearchGetAndSuggestPermissionsTests extends ShieldIntegTestCase {
|
|||
|
||||
Client client = internalCluster().transportClient();
|
||||
|
||||
MultiSearchResponse response = client.prepareMultiSearch().add(searchRequest("a").types("type"))
|
||||
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd"))
|
||||
MultiSearchResponse response = client.filterWithHeader(Collections.singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd")))
|
||||
.prepareMultiSearch().add(searchRequest("a").types("type"))
|
||||
.get();
|
||||
assertNotNull(response);
|
||||
assertThat(response.getResponses().length, is(1));
|
||||
|
|
|
@ -19,8 +19,11 @@ import org.junit.After;
|
|||
import org.junit.Before;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.BASIC_AUTH_HEADER;
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertThrows;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -85,9 +88,11 @@ public class ShieldClearScrollTests extends ShieldIntegTestCase {
|
|||
public void testThatClearingAllScrollIdsWorks() throws Exception {
|
||||
String shieldUser = "allowed_user:change_me";
|
||||
String basicAuth = basicAuthHeaderValue("allowed_user", new SecuredString("change_me".toCharArray()));
|
||||
ClearScrollResponse clearScrollResponse = internalCluster().transportClient().prepareClearScroll()
|
||||
.putHeader("shield.user", shieldUser)
|
||||
.putHeader("Authorization", basicAuth)
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("shield.user", shieldUser);
|
||||
headers.put(BASIC_AUTH_HEADER, basicAuth);
|
||||
ClearScrollResponse clearScrollResponse = internalCluster().transportClient().filterWithHeader(headers)
|
||||
.prepareClearScroll()
|
||||
.addScrollId("_all").get();
|
||||
assertThat(clearScrollResponse.isSucceeded(), is(true));
|
||||
|
||||
|
@ -97,10 +102,11 @@ public class ShieldClearScrollTests extends ShieldIntegTestCase {
|
|||
public void testThatClearingAllScrollIdsRequirePermissions() throws Exception {
|
||||
String shieldUser = "denied_user:change_me";
|
||||
String basicAuth = basicAuthHeaderValue("denied_user", new SecuredString("change_me".toCharArray()));
|
||||
|
||||
assertThrows(internalCluster().transportClient().prepareClearScroll()
|
||||
.putHeader("shield.user", shieldUser)
|
||||
.putHeader("Authorization", basicAuth)
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("shield.user", shieldUser);
|
||||
headers.put(BASIC_AUTH_HEADER, basicAuth);
|
||||
assertThrows(internalCluster().transportClient().filterWithHeader(headers)
|
||||
.prepareClearScroll()
|
||||
.addScrollId("_all"), ElasticsearchSecurityException.class, "action [cluster:admin/indices/scroll/clear_all] is unauthorized for user [denied_user]");
|
||||
|
||||
// deletion of scroll ids should work
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.elasticsearch.ElasticsearchException;
|
|||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.action.get.GetResponse;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.logging.ESLoggerFactory;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.shield.authc.activedirectory.ActiveDirectoryRealm;
|
||||
|
@ -24,6 +25,7 @@ import org.junit.BeforeClass;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
|
@ -107,20 +109,19 @@ abstract public class AbstractAdLdapRealmTestCase extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
protected void assertAccessAllowed(String user, String index) throws IOException {
|
||||
IndexResponse indexResponse = client().prepareIndex(index, "type").
|
||||
Client client = client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, userHeader(user, PASSWORD)));
|
||||
IndexResponse indexResponse = client.prepareIndex(index, "type").
|
||||
setSource(jsonBuilder()
|
||||
.startObject()
|
||||
.field("name", "value")
|
||||
.endObject())
|
||||
.putHeader(BASIC_AUTH_HEADER, userHeader(user, PASSWORD))
|
||||
.execute().actionGet();
|
||||
|
||||
assertThat("user " + user + " should have write access to index " + index, indexResponse.isCreated(), is(true));
|
||||
|
||||
refresh();
|
||||
|
||||
GetResponse getResponse = client().prepareGet(index, "type", indexResponse.getId())
|
||||
.putHeader(BASIC_AUTH_HEADER, userHeader(user, PASSWORD))
|
||||
GetResponse getResponse = client.prepareGet(index, "type", indexResponse.getId())
|
||||
.get();
|
||||
|
||||
assertThat("user " + user + " should have read access to index " + index, getResponse.getId(), equalTo(indexResponse.getId()));
|
||||
|
@ -128,12 +129,12 @@ abstract public class AbstractAdLdapRealmTestCase extends ShieldIntegTestCase {
|
|||
|
||||
protected void assertAccessDenied(String user, String index) throws IOException {
|
||||
try {
|
||||
client().prepareIndex(index, "type").
|
||||
client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, userHeader(user, PASSWORD)))
|
||||
.prepareIndex(index, "type").
|
||||
setSource(jsonBuilder()
|
||||
.startObject()
|
||||
.field("name", "value")
|
||||
.endObject())
|
||||
.putHeader(BASIC_AUTH_HEADER, userHeader(user, PASSWORD))
|
||||
.execute().actionGet();
|
||||
fail("Write access to index " + index + " should not be allowed for user " + user);
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.elasticsearch.action.ActionRequest;
|
|||
import org.elasticsearch.action.search.SearchScrollRequest;
|
||||
import org.elasticsearch.action.support.ActionFilterChain;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.action.interceptor.RequestInterceptor;
|
||||
import org.elasticsearch.shield.audit.AuditTrail;
|
||||
|
@ -20,6 +21,7 @@ import org.elasticsearch.shield.crypto.CryptoService;
|
|||
import org.elasticsearch.shield.license.ShieldLicenseState;
|
||||
import org.elasticsearch.tasks.Task;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
@ -56,7 +58,9 @@ public class ShieldActionFilterTests extends ESTestCase {
|
|||
shieldLicenseState = mock(ShieldLicenseState.class);
|
||||
when(shieldLicenseState.securityEnabled()).thenReturn(true);
|
||||
when(shieldLicenseState.statsAndHealthEnabled()).thenReturn(true);
|
||||
filter = new ShieldActionFilter(Settings.EMPTY, authcService, authzService, cryptoService, auditTrail, shieldLicenseState, new ShieldActionMapper(), new HashSet<RequestInterceptor>());
|
||||
ThreadPool threadPool = mock(ThreadPool.class);
|
||||
when(threadPool.getThreadContext()).thenReturn(new ThreadContext(Settings.EMPTY));
|
||||
filter = new ShieldActionFilter(Settings.EMPTY, authcService, authzService, cryptoService, auditTrail, shieldLicenseState, new ShieldActionMapper(), new HashSet<RequestInterceptor>(), threadPool);
|
||||
}
|
||||
|
||||
public void testApply() throws Exception {
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.junit.After;
|
|||
import org.junit.Before;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
|
@ -197,7 +198,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
client().prepareIndex("idx", "doc", "1").setSource("body", "foo").setRefresh(true).get();
|
||||
|
||||
String token = basicAuthHeaderValue("joe", new SecuredString("s3krit".toCharArray()));
|
||||
SearchResponse searchResp = client().prepareSearch("idx").putHeader("Authorization", token).get();
|
||||
SearchResponse searchResp = client().filterWithHeader(Collections.singletonMap("Authorization", token)).prepareSearch("idx").get();
|
||||
|
||||
assertEquals(searchResp.getHits().getTotalHits(), 1L);
|
||||
}
|
||||
|
@ -223,7 +224,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
// Index a document with the default test user
|
||||
client().prepareIndex("idx", "doc", "1").setSource("body", "foo").setRefresh(true).get();
|
||||
String token = basicAuthHeaderValue("joe", new SecuredString("s3krit".toCharArray()));
|
||||
SearchResponse searchResp = client().prepareSearch("idx").putHeader("Authorization", token).get();
|
||||
SearchResponse searchResp = client().filterWithHeader(Collections.singletonMap("Authorization", token)).prepareSearch("idx").get();
|
||||
|
||||
assertEquals(searchResp.getHits().getTotalHits(), 1L);
|
||||
|
||||
|
@ -234,7 +235,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
|
||||
try {
|
||||
client().prepareSearch("idx").putHeader("Authorization", token).get();
|
||||
client().filterWithHeader(Collections.singletonMap("Authorization", token)).prepareSearch("idx").get();
|
||||
fail("authentication with old credentials after an update to the user should fail!");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
// expected
|
||||
|
@ -242,7 +243,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
token = basicAuthHeaderValue("joe", new SecuredString("s3krit2".toCharArray()));
|
||||
searchResp = client().prepareSearch("idx").putHeader("Authorization", token).get();
|
||||
searchResp = client().filterWithHeader(Collections.singletonMap("Authorization", token)).prepareSearch("idx").get();
|
||||
assertEquals(searchResp.getHits().getTotalHits(), 1L);
|
||||
}
|
||||
|
||||
|
@ -267,14 +268,14 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
// Index a document with the default test user
|
||||
client().prepareIndex("idx", "doc", "1").setSource("body", "foo").setRefresh(true).get();
|
||||
String token = basicAuthHeaderValue("joe", new SecuredString("s3krit".toCharArray()));
|
||||
SearchResponse searchResp = client().prepareSearch("idx").putHeader("Authorization", token).get();
|
||||
SearchResponse searchResp = client().filterWithHeader(Collections.singletonMap("Authorization", token)).prepareSearch("idx").get();
|
||||
|
||||
assertEquals(searchResp.getHits().getTotalHits(), 1L);
|
||||
|
||||
DeleteUserResponse response = c.prepareDeleteUser().user("joe").get();
|
||||
assertThat(response.found(), is(true));
|
||||
try {
|
||||
client().prepareSearch("idx").putHeader("Authorization", token).get();
|
||||
client().filterWithHeader(Collections.singletonMap("Authorization", token)).prepareSearch("idx").get();
|
||||
fail("authentication with a deleted user should fail!");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
// expected
|
||||
|
@ -304,7 +305,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
|
||||
if (authenticate) {
|
||||
final String token = basicAuthHeaderValue("joe", new SecuredString("s3krit".toCharArray()));
|
||||
ClusterHealthResponse response = client().admin().cluster().prepareHealth().putHeader("Authorization", token).get();
|
||||
ClusterHealthResponse response = client().filterWithHeader(Collections.singletonMap("Authorization", token)).admin().cluster().prepareHealth().get();
|
||||
assertFalse(response.isTimedOut());
|
||||
c.prepareAddRole()
|
||||
.name("test_role")
|
||||
|
@ -313,7 +314,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
new String[]{"body", "title"}, new BytesArray("{\"match_all\": {}}"))
|
||||
.get();
|
||||
try {
|
||||
client().admin().cluster().prepareHealth().putHeader("Authorization", token).get();
|
||||
client().filterWithHeader(Collections.singletonMap("Authorization", token)).admin().cluster().prepareHealth().get();
|
||||
fail("user should not be able to execute any cluster actions!");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
assertThat(e.status(), is(RestStatus.FORBIDDEN));
|
||||
|
@ -356,11 +357,11 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
ensureGreen(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
|
||||
|
||||
final String token = basicAuthHeaderValue("joe", new SecuredString("s3krit".toCharArray()));
|
||||
ClusterHealthResponse response = client().admin().cluster().prepareHealth().putHeader("Authorization", token).get();
|
||||
ClusterHealthResponse response = client().filterWithHeader(Collections.singletonMap("Authorization", token)).admin().cluster().prepareHealth().get();
|
||||
assertFalse(response.isTimedOut());
|
||||
c.prepareDeleteRole().role("test_role").get();
|
||||
try {
|
||||
client().admin().cluster().prepareHealth().putHeader("Authorization", token).get();
|
||||
client().filterWithHeader(Collections.singletonMap("Authorization", token)).admin().cluster().prepareHealth().get();
|
||||
fail("user should not be able to execute any actions!");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
assertThat(e.status(), is(RestStatus.FORBIDDEN));
|
||||
|
|
|
@ -194,7 +194,7 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase {
|
|||
}
|
||||
settings = builder.build();
|
||||
|
||||
doThrow(new IllegalStateException("indexing user should not be attached when sending remotely")).when(authService).attachUserHeaderIfMissing(any(TransportMessage.class), eq(user.user()));
|
||||
doThrow(new IllegalStateException("indexing user should not be attached when sending remotely")).when(authService).attachUserHeaderIfMissing(eq(user.user()));
|
||||
}
|
||||
|
||||
settings = Settings.builder().put(settings).put("path.home", createTempDir()).build();
|
||||
|
|
|
@ -24,7 +24,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.test.InternalTestCluster.clusterName;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
@ -107,7 +106,8 @@ public class RemoteIndexAuditTrailStartingTests extends ShieldIntegTestCase {
|
|||
return builder.build();
|
||||
}
|
||||
};
|
||||
remoteCluster = new InternalTestCluster("network", randomLong(), createTempDir(), numNodes, numNodes, cluster2Name, cluster2SettingsSource, 0, false, SECOND_CLUSTER_NODE_PREFIX, getMockPlugins(), Function.identity());
|
||||
remoteCluster = new InternalTestCluster("network", randomLong(), createTempDir(), numNodes, numNodes, cluster2Name,
|
||||
cluster2SettingsSource, 0, false, SECOND_CLUSTER_NODE_PREFIX, getMockPlugins(), getClientWrapper());
|
||||
remoteCluster.beforeTest(getRandom(), 0.5);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.common.transport.DummyTransportAddress;
|
|||
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||
import org.elasticsearch.common.transport.LocalTransportAddress;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.audit.logfile.CapturingLogger.Level;
|
||||
|
@ -102,6 +103,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
private String prefix;
|
||||
private Settings settings;
|
||||
private Transport transport;
|
||||
private ThreadContext threadContext;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
|
@ -118,10 +120,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testAnonymousAccessDeniedTransport() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);
|
||||
auditTrail.anonymousAccessDenied("_action", message);
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
|
@ -154,8 +157,9 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
String expectedMessage = prepareRestContent(request);
|
||||
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
auditTrail.anonymousAccessDenied(request);
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
|
@ -174,10 +178,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testAuthenticationFailed() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);;
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);;
|
||||
auditTrail.authenticationFailed(new MockToken(), "_action", message);
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
|
@ -202,10 +207,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testAuthenticationFailedNoToken() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);;
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);;
|
||||
auditTrail.authenticationFailed("_action", message);
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
|
@ -230,13 +236,14 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testAuthenticationFailedRest() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
RestRequest request = mock(RestRequest.class);
|
||||
InetAddress address = forge("_hostname", randomBoolean() ? "127.0.0.1" : "::1");
|
||||
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
||||
when(request.uri()).thenReturn("_uri");
|
||||
String expectedMessage = prepareRestContent(request);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
auditTrail.authenticationFailed(new MockToken(), request);
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
|
@ -253,13 +260,14 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testAuthenticationFailedRestNoToken() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
RestRequest request = mock(RestRequest.class);
|
||||
InetAddress address = forge("_hostname", randomBoolean() ? "127.0.0.1" : "::1");
|
||||
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
||||
when(request.uri()).thenReturn("_uri");
|
||||
String expectedMessage = prepareRestContent(request);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
auditTrail.authenticationFailed(request);
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
|
@ -276,10 +284,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testAuthenticationFailedRealm() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);;
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);;
|
||||
auditTrail.authenticationFailed("_realm", new MockToken(), "_action", message);
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
|
@ -300,13 +309,14 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testAuthenticationFailedRealmRest() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
RestRequest request = mock(RestRequest.class);
|
||||
InetAddress address = forge("_hostname", randomBoolean() ? "127.0.0.1" : "::1");
|
||||
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
||||
when(request.uri()).thenReturn("_uri");
|
||||
String expectedMessage = prepareRestContent(request);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
auditTrail.authenticationFailed("_realm", new MockToken(), request);
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
|
@ -323,10 +333,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testAccessGranted() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);
|
||||
boolean runAs = randomBoolean();
|
||||
User user;
|
||||
if (runAs) {
|
||||
|
@ -362,10 +373,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testAccessGrantedInternalSystemAction() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);
|
||||
auditTrail.accessGranted(User.SYSTEM, "internal:_action", message);
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
|
@ -386,10 +398,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testAccessGrantedInternalSystemActionNonSystemUser() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);
|
||||
boolean runAs = randomBoolean();
|
||||
User user;
|
||||
if (runAs) {
|
||||
|
@ -425,10 +438,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testAccessDenied() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);
|
||||
boolean runAs = randomBoolean();
|
||||
User user;
|
||||
if (runAs) {
|
||||
|
@ -462,11 +476,12 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testTamperedRequest() throws Exception {
|
||||
String action = "_action";
|
||||
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
auditTrail.tamperedRequest(action, message);
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
|
@ -491,8 +506,6 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testTamperedRequestWithUser() throws Exception {
|
||||
String action = "_action";
|
||||
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);
|
||||
final boolean runAs = randomBoolean();
|
||||
User user;
|
||||
if (runAs) {
|
||||
|
@ -502,8 +515,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
}
|
||||
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
auditTrail.tamperedRequest(user, action, message);
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
|
@ -528,8 +544,9 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testConnectionDenied() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
InetAddress inetAddress = InetAddress.getLoopbackAddress();
|
||||
ShieldIpFilterRule rule = new ShieldIpFilterRule(false, "_all");
|
||||
auditTrail.connectionDenied(inetAddress, "default", rule);
|
||||
|
@ -548,8 +565,9 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testConnectionGranted() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
InetAddress inetAddress = InetAddress.getLoopbackAddress();
|
||||
ShieldIpFilterRule rule = IPFilter.DEFAULT_PROFILE_ACCEPT_ALL;
|
||||
auditTrail.connectionGranted(inetAddress, "default", rule);
|
||||
|
@ -570,10 +588,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testRunAsGranted() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
TransportMessage message = new MockMessage();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
TransportMessage message = new MockMessage(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);
|
||||
User user = new User("_username", new String[]{"r1"}, new User("running as", new String[] {"r2"}));
|
||||
auditTrail.runAsGranted(user, "_action", message);
|
||||
switch (level) {
|
||||
|
@ -593,10 +612,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
public void testRunAsDenied() throws Exception {
|
||||
for (Level level : Level.values()) {
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
CapturingLogger logger = new CapturingLogger(level);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger).start();
|
||||
TransportMessage message = new MockMessage();
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport);
|
||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, transport, logger, threadContext).start();
|
||||
TransportMessage message = new MockMessage(threadContext);
|
||||
String origins = LoggingAuditTrail.originAttributes(message, transport, threadContext);
|
||||
User user = new User("_username", new String[]{"r1"}, new User("running as", new String[] {"r2"}));
|
||||
auditTrail.runAsDenied(user, "_action", message);
|
||||
switch (level) {
|
||||
|
@ -615,9 +635,10 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testOriginAttributes() throws Exception {
|
||||
MockMessage message = new MockMessage();
|
||||
String text = LoggingAuditTrail.originAttributes(message, transport);;
|
||||
InetSocketAddress restAddress = RemoteHostHeader.restRemoteAddress(message);
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
MockMessage message = new MockMessage(threadContext);
|
||||
String text = LoggingAuditTrail.originAttributes(message, transport, threadContext);;
|
||||
InetSocketAddress restAddress = RemoteHostHeader.restRemoteAddress(threadContext);
|
||||
if (restAddress != null) {
|
||||
assertThat(text, equalTo("origin_type=[rest], origin_address=[" + NetworkAddress.formatAddress(restAddress.getAddress()) + "]"));
|
||||
return;
|
||||
|
@ -662,7 +683,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
|
||||
private static class MockMessage extends TransportMessage<MockMessage> {
|
||||
|
||||
private MockMessage() throws IOException {
|
||||
private MockMessage(ThreadContext threadContext) throws IOException {
|
||||
if (randomBoolean()) {
|
||||
if (randomBoolean()) {
|
||||
remoteAddress(new LocalTransportAddress("local_host"));
|
||||
|
@ -671,19 +692,19 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
RemoteHostHeader.putRestRemoteAddress(this, new InetSocketAddress(forge("localhost", "127.0.0.1"), 1234));
|
||||
RemoteHostHeader.putRestRemoteAddress(threadContext, new InetSocketAddress(forge("localhost", "127.0.0.1"), 1234));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MockIndicesRequest extends TransportMessage<MockIndicesRequest> implements IndicesRequest {
|
||||
|
||||
private MockIndicesRequest() throws IOException {
|
||||
private MockIndicesRequest(ThreadContext threadContext) throws IOException {
|
||||
if (randomBoolean()) {
|
||||
remoteAddress(new LocalTransportAddress("_host"));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
RemoteHostHeader.putRestRemoteAddress(this, new InetSocketAddress(forge("localhost", "127.0.0.1"), 1234));
|
||||
RemoteHostHeader.putRestRemoteAddress(threadContext, new InetSocketAddress(forge("localhost", "127.0.0.1"), 1234));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.elasticsearch.ElasticsearchSecurityException;
|
|||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.shield.ShieldSettingsFilter;
|
||||
|
@ -21,6 +22,7 @@ import org.elasticsearch.shield.crypto.CryptoService;
|
|||
import org.elasticsearch.shield.license.ShieldLicenseState;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.rest.FakeRestRequest;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
|
@ -68,6 +70,8 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
AuthenticationToken token;
|
||||
CryptoService cryptoService;
|
||||
AnonymousService anonymousService;
|
||||
ThreadPool threadPool;
|
||||
ThreadContext threadContext;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
|
@ -95,13 +99,16 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
auditTrail = mock(AuditTrail.class);
|
||||
anonymousService = mock(AnonymousService.class);
|
||||
service = new InternalAuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, anonymousService, new DefaultAuthenticationFailureHandler());
|
||||
threadPool = mock(ThreadPool.class);
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
when(threadPool.getThreadContext()).thenReturn(threadContext);
|
||||
service = new InternalAuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, anonymousService, new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testTokenFirstMissingSecondFound() throws Exception {
|
||||
when(firstRealm.token(message)).thenReturn(null);
|
||||
when(secondRealm.token(message)).thenReturn(token);
|
||||
when(firstRealm.token(threadContext)).thenReturn(null);
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
|
||||
AuthenticationToken result = service.token("_action", message);
|
||||
assertThat(result, notNullValue());
|
||||
|
@ -113,19 +120,19 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
AuthenticationToken token = service.token("_action", message);
|
||||
assertThat(token, nullValue());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
assertThat(message.getContext().get(InternalAuthenticationService.TOKEN_KEY), nullValue());
|
||||
assertThat(threadContext.getTransient(InternalAuthenticationService.TOKEN_KEY), nullValue());
|
||||
}
|
||||
|
||||
public void testTokenCached() throws Exception {
|
||||
message.putInContext(InternalAuthenticationService.TOKEN_KEY, token);
|
||||
threadContext.putTransient(InternalAuthenticationService.TOKEN_KEY, token);
|
||||
AuthenticationToken result = service.token("_action", message);
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result, is(token));
|
||||
verifyZeroInteractions(auditTrail);
|
||||
verifyZeroInteractions(firstRealm);
|
||||
verifyZeroInteractions(secondRealm);
|
||||
assertThat(message.getContext().get(InternalAuthenticationService.TOKEN_KEY), notNullValue());
|
||||
assertThat(message.getContext().get(InternalAuthenticationService.TOKEN_KEY), is((Object) token));
|
||||
assertThat(threadContext.getTransient(InternalAuthenticationService.TOKEN_KEY), notNullValue());
|
||||
assertThat(threadContext.getTransient(InternalAuthenticationService.TOKEN_KEY), is((Object) token));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -145,9 +152,10 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
assertThat(result, notNullValue());
|
||||
assertThat(result, is(user));
|
||||
verify(auditTrail).authenticationFailed("esusers", token, "_action", message);
|
||||
assertThat(message.getContext().get(InternalAuthenticationService.USER_KEY), notNullValue());
|
||||
assertThat(message.getContext().get(InternalAuthenticationService.USER_KEY), sameInstance((Object) user));
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_encoded_user"));
|
||||
User user1 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user1, notNullValue());
|
||||
assertThat(user1, sameInstance(user));
|
||||
assertThat(threadContext.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_encoded_user"));
|
||||
}
|
||||
|
||||
public void testAuthenticateFirstNotSupportingSecondSucceeds() throws Exception {
|
||||
|
@ -166,14 +174,15 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
assertThat(result, is(user));
|
||||
verifyZeroInteractions(auditTrail);
|
||||
verify(firstRealm, never()).authenticate(token);
|
||||
assertThat(message.getContext().get(InternalAuthenticationService.USER_KEY), notNullValue());
|
||||
assertThat(message.getContext().get(InternalAuthenticationService.USER_KEY), is((Object) user));
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_encoded_user"));
|
||||
User user1 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user1, notNullValue());
|
||||
assertThat(user1, is((Object) user));
|
||||
assertThat(threadContext.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_encoded_user"));
|
||||
}
|
||||
|
||||
public void testAuthenticateCached() throws Exception {
|
||||
User user = new User("_username", "r1");
|
||||
message.putInContext(InternalAuthenticationService.USER_KEY, user);
|
||||
threadContext.putTransient(InternalAuthenticationService.USER_KEY, user);
|
||||
User result = service.authenticate("_action", message, null);
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result, is(user));
|
||||
|
@ -181,12 +190,13 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
verifyZeroInteractions(firstRealm);
|
||||
verifyZeroInteractions(secondRealm);
|
||||
verifyZeroInteractions(cryptoService);
|
||||
assertThat(message.getContext().get(InternalAuthenticationService.USER_KEY), notNullValue());
|
||||
assertThat(message.getContext().get(InternalAuthenticationService.USER_KEY), is((Object) user));
|
||||
User user1 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user1, notNullValue());
|
||||
assertThat(user1, is(user));
|
||||
}
|
||||
|
||||
public void testAuthenticateNonExistentRestRequestUserThrowsAuthenticationException() throws Exception {
|
||||
when(firstRealm.token(restRequest)).thenReturn(new UsernamePasswordToken("idonotexist", new SecuredString("passwd".toCharArray())));
|
||||
when(firstRealm.token(threadContext)).thenReturn(new UsernamePasswordToken("idonotexist", new SecuredString("passwd".toCharArray())));
|
||||
try {
|
||||
service.authenticate(restRequest);
|
||||
fail("Authentication was successful but should not");
|
||||
|
@ -197,17 +207,17 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
public void testTokenRestExists() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
when(firstRealm.token(restRequest)).thenReturn(null);
|
||||
when(secondRealm.token(restRequest)).thenReturn(token);
|
||||
AuthenticationToken foundToken = service.token(restRequest);
|
||||
when(firstRealm.token(threadContext)).thenReturn(null);
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
AuthenticationToken foundToken = service.token();
|
||||
assertThat(foundToken, is(token));
|
||||
assertThat(restRequest.getFromContext(InternalAuthenticationService.TOKEN_KEY), equalTo((Object) token));
|
||||
assertThat(threadContext.getTransient(InternalAuthenticationService.TOKEN_KEY), equalTo((Object) token));
|
||||
}
|
||||
|
||||
public void testTokenRestMissing() throws Exception {
|
||||
when(firstRealm.token(restRequest)).thenReturn(null);
|
||||
when(secondRealm.token(restRequest)).thenReturn(null);
|
||||
AuthenticationToken token = service.token(restRequest);
|
||||
when(firstRealm.token(threadContext)).thenReturn(null);
|
||||
when(secondRealm.token(threadContext)).thenReturn(null);
|
||||
AuthenticationToken token = service.token();
|
||||
assertThat(token, nullValue());
|
||||
}
|
||||
|
||||
|
@ -224,7 +234,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
public void testUserHeader() throws Exception {
|
||||
User user = new User("_username", "r1");
|
||||
when(firstRealm.token(message)).thenReturn(token);
|
||||
when(firstRealm.token(threadContext)).thenReturn(token);
|
||||
when(firstRealm.supports(token)).thenReturn(true);
|
||||
when(firstRealm.authenticate(token)).thenReturn(user);
|
||||
when(cryptoService.sign(InternalAuthenticationService.encodeUser(user, null))).thenReturn("_signed_user");
|
||||
|
@ -233,14 +243,14 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
User result = service.authenticate("_action", message, null);
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result, is(user));
|
||||
String userStr = (String) message.getHeader(InternalAuthenticationService.USER_KEY);
|
||||
String userStr = threadContext.getHeader(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(userStr, notNullValue());
|
||||
assertThat(userStr, equalTo("_signed_user"));
|
||||
}
|
||||
|
||||
public void testAuthenticateTransportAnonymous() throws Exception {
|
||||
when(firstRealm.token(message)).thenReturn(null);
|
||||
when(secondRealm.token(message)).thenReturn(null);
|
||||
when(firstRealm.token(threadContext)).thenReturn(null);
|
||||
when(secondRealm.token(threadContext)).thenReturn(null);
|
||||
try {
|
||||
service.authenticate("_action", message, null);
|
||||
fail("expected an authentication exception when trying to authenticate an anonymous message");
|
||||
|
@ -252,8 +262,8 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testAuthenticateRestAnonymous() throws Exception {
|
||||
when(firstRealm.token(restRequest)).thenReturn(null);
|
||||
when(secondRealm.token(restRequest)).thenReturn(null);
|
||||
when(firstRealm.token(threadContext)).thenReturn(null);
|
||||
when(secondRealm.token(threadContext)).thenReturn(null);
|
||||
try {
|
||||
service.authenticate(restRequest);
|
||||
fail("expected an authentication exception when trying to authenticate an anonymous message");
|
||||
|
@ -265,65 +275,74 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testAuthenticateTransportFallback() throws Exception {
|
||||
when(firstRealm.token(message)).thenReturn(null);
|
||||
when(secondRealm.token(message)).thenReturn(null);
|
||||
when(firstRealm.token(threadContext)).thenReturn(null);
|
||||
when(secondRealm.token(threadContext)).thenReturn(null);
|
||||
User user1 = new User("username", "r1", "r2");
|
||||
when(cryptoService.sign(InternalAuthenticationService.encodeUser(user1, null))).thenReturn("_signed_user");
|
||||
User user2 = service.authenticate("_action", message, user1);
|
||||
assertThat(user1, sameInstance(user2));
|
||||
assertThat(message.getFromContext(InternalAuthenticationService.USER_KEY), sameInstance((Object) user2));
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_signed_user"));
|
||||
User user3 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user3, sameInstance(user2));
|
||||
assertThat(threadContext.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_signed_user"));
|
||||
}
|
||||
|
||||
public void testAuthenticateTransportSuccessNoFallback() throws Exception {
|
||||
User user1 = new User("username", "r1", "r2");
|
||||
when(firstRealm.token(message)).thenReturn(token);
|
||||
when(firstRealm.token(threadContext)).thenReturn(token);
|
||||
when(firstRealm.supports(token)).thenReturn(true);
|
||||
when(firstRealm.authenticate(token)).thenReturn(user1);
|
||||
when(cryptoService.sign(InternalAuthenticationService.encodeUser(user1, null))).thenReturn("_signed_user");
|
||||
User user2 = service.authenticate("_action", message, null);
|
||||
assertThat(user1, sameInstance(user2));
|
||||
assertThat(message.getFromContext(InternalAuthenticationService.USER_KEY), sameInstance((Object) user2));
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_signed_user"));
|
||||
User user3 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user3, sameInstance(user2));
|
||||
assertThat(threadContext.getHeader(InternalAuthenticationService.USER_KEY), equalTo("_signed_user"));
|
||||
}
|
||||
|
||||
public void testAuthenticateTransportSuccessWithFallback() throws Exception {
|
||||
User user1 = new User("username", "r1", "r2");
|
||||
when(firstRealm.token(message)).thenReturn(token);
|
||||
when(firstRealm.token(threadContext)).thenReturn(token);
|
||||
when(firstRealm.supports(token)).thenReturn(true);
|
||||
when(firstRealm.authenticate(token)).thenReturn(user1);
|
||||
when(cryptoService.sign(InternalAuthenticationService.encodeUser(user1, null))).thenReturn("_signed_user");
|
||||
User user2 = service.authenticate("_action", message, User.SYSTEM);
|
||||
assertThat(user1, sameInstance(user2));
|
||||
assertThat(message.getFromContext(InternalAuthenticationService.USER_KEY), sameInstance((Object) user2));
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_signed_user"));
|
||||
User user3 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user3, sameInstance((Object) user2));
|
||||
assertThat(threadContext.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_signed_user"));
|
||||
}
|
||||
|
||||
public void testAuthenticateRestSuccess() throws Exception {
|
||||
User user1 = new User("username", "r1", "r2");
|
||||
when(firstRealm.token(restRequest)).thenReturn(token);
|
||||
when(firstRealm.token(threadContext)).thenReturn(token);
|
||||
when(firstRealm.supports(token)).thenReturn(true);
|
||||
when(firstRealm.authenticate(token)).thenReturn(user1);
|
||||
User user2 = service.authenticate(restRequest);
|
||||
assertThat(user1, sameInstance(user2));
|
||||
assertThat(restRequest.getFromContext(InternalAuthenticationService.USER_KEY), sameInstance((Object) user2));
|
||||
User user3 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user3, sameInstance(user2));
|
||||
}
|
||||
|
||||
public void testAutheticateTransportContextAndHeader() throws Exception {
|
||||
User user1 = new User("username", "r1", "r2");
|
||||
when(firstRealm.token(message)).thenReturn(token);
|
||||
when(firstRealm.token(threadContext)).thenReturn(token);
|
||||
when(firstRealm.supports(token)).thenReturn(true);
|
||||
when(firstRealm.authenticate(token)).thenReturn(user1);
|
||||
when(cryptoService.sign(InternalAuthenticationService.encodeUser(user1, null))).thenReturn("_signed_user");
|
||||
User user2 = service.authenticate("_action", message, User.SYSTEM);
|
||||
assertThat(user1, sameInstance(user2));
|
||||
assertThat(message.getFromContext(InternalAuthenticationService.USER_KEY), sameInstance((Object) user2));
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_signed_user"));
|
||||
User user3 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user3, sameInstance(user2));
|
||||
assertThat(threadContext.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_signed_user"));
|
||||
reset(firstRealm);
|
||||
|
||||
// checking authentication from the context
|
||||
InternalMessage message1 = new InternalMessage();
|
||||
message1.copyContextFrom(message);
|
||||
ThreadContext threadContext1 = new ThreadContext(Settings.EMPTY);
|
||||
when(threadPool.getThreadContext()).thenReturn(threadContext1);
|
||||
service = new InternalAuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, anonymousService, new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
|
||||
threadContext1.putTransient(InternalAuthenticationService.USER_KEY, threadContext.getTransient(InternalAuthenticationService.USER_KEY));
|
||||
User user = service.authenticate("_action", message1, User.SYSTEM);
|
||||
assertThat(user, sameInstance(user1));
|
||||
verifyZeroInteractions(firstRealm);
|
||||
|
@ -331,35 +350,46 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
|
||||
// checking authentication from the user header
|
||||
message1.putHeader(InternalAuthenticationService.USER_KEY, message.getHeader(InternalAuthenticationService.USER_KEY));
|
||||
threadContext1 = new ThreadContext(Settings.EMPTY);
|
||||
when(threadPool.getThreadContext()).thenReturn(threadContext1);
|
||||
service = new InternalAuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, anonymousService, new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
threadContext1.putHeader(InternalAuthenticationService.USER_KEY, threadContext.getHeader(InternalAuthenticationService.USER_KEY));
|
||||
when(cryptoService.unsignAndVerify("_signed_user")).thenReturn(InternalAuthenticationService.encodeUser(user1, null));
|
||||
|
||||
BytesStreamOutput output = new BytesStreamOutput();
|
||||
message1.writeTo(output);
|
||||
threadContext1.writeTo(output);
|
||||
StreamInput input = StreamInput.wrap(output.bytes());
|
||||
InternalMessage message2 = new InternalMessage();
|
||||
message2.readFrom(input);
|
||||
user = service.authenticate("_action", message2, User.SYSTEM);
|
||||
threadContext1 = new ThreadContext(Settings.EMPTY);
|
||||
threadContext1.readHeaders(input);
|
||||
|
||||
when(threadPool.getThreadContext()).thenReturn(threadContext1);
|
||||
service = new InternalAuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, anonymousService, new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
user = service.authenticate("_action", new InternalMessage(), User.SYSTEM);
|
||||
assertThat(user, equalTo(user1));
|
||||
verifyZeroInteractions(firstRealm);
|
||||
}
|
||||
|
||||
public void testAutheticateTransportContextAndHeaderNoSigning() throws Exception {
|
||||
Settings settings = Settings.builder().put(InternalAuthenticationService.SETTING_SIGN_USER_HEADER, false).build();
|
||||
service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, anonymousService, new DefaultAuthenticationFailureHandler());
|
||||
service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, anonymousService, new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
|
||||
User user1 = new User("username", "r1", "r2");
|
||||
when(firstRealm.supports(token)).thenReturn(true);
|
||||
when(firstRealm.token(message)).thenReturn(token);
|
||||
when(firstRealm.token(threadContext)).thenReturn(token);
|
||||
when(firstRealm.authenticate(token)).thenReturn(user1);
|
||||
User user2 = service.authenticate("_action", message, User.SYSTEM);
|
||||
assertThat(user1, sameInstance(user2));
|
||||
assertThat(message.getFromContext(InternalAuthenticationService.USER_KEY), sameInstance((Object) user2));
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) InternalAuthenticationService.encodeUser(user1, null)));
|
||||
User user3 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user3, sameInstance(user2));
|
||||
assertThat(threadContext.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) InternalAuthenticationService.encodeUser(user1, null)));
|
||||
reset(firstRealm);
|
||||
|
||||
// checking authentication from the context
|
||||
InternalMessage message1 = new InternalMessage();
|
||||
message1.copyContextFrom(message);
|
||||
ThreadContext threadContext1 = new ThreadContext(Settings.EMPTY);
|
||||
when(threadPool.getThreadContext()).thenReturn(threadContext1);
|
||||
service = new InternalAuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, anonymousService, new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
threadContext1.putTransient(InternalAuthenticationService.USER_KEY, threadContext.getTransient(InternalAuthenticationService.USER_KEY));
|
||||
User user = service.authenticate("_action", message1, User.SYSTEM);
|
||||
assertThat(user, sameInstance(user1));
|
||||
verifyZeroInteractions(firstRealm);
|
||||
|
@ -367,13 +397,18 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
|
||||
// checking authentication from the user header
|
||||
message1.putHeader(InternalAuthenticationService.USER_KEY, message.getHeader(InternalAuthenticationService.USER_KEY));
|
||||
threadContext1 = new ThreadContext(Settings.EMPTY);
|
||||
threadContext1.putHeader(InternalAuthenticationService.USER_KEY, threadContext.getHeader(InternalAuthenticationService.USER_KEY));
|
||||
|
||||
BytesStreamOutput output = new BytesStreamOutput();
|
||||
message1.writeTo(output);
|
||||
threadContext1.writeTo(output);
|
||||
StreamInput input = StreamInput.wrap(output.bytes());
|
||||
InternalMessage message2 = new InternalMessage();
|
||||
message2.readFrom(input);
|
||||
user = service.authenticate("_action", message2, User.SYSTEM);
|
||||
threadContext1 = new ThreadContext(Settings.EMPTY);
|
||||
threadContext1.readHeaders(input);
|
||||
|
||||
when(threadPool.getThreadContext()).thenReturn(threadContext1);
|
||||
service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, anonymousService, new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
user = service.authenticate("_action", new InternalMessage(), User.SYSTEM);
|
||||
assertThat(user, equalTo(user1));
|
||||
verifyZeroInteractions(firstRealm);
|
||||
|
||||
|
@ -382,7 +417,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
public void testAuthenticateTamperedUser() throws Exception {
|
||||
InternalMessage message = new InternalMessage();
|
||||
message.putHeader(InternalAuthenticationService.USER_KEY, "_signed_user");
|
||||
threadContext.putHeader(InternalAuthenticationService.USER_KEY, "_signed_user");
|
||||
when(cryptoService.unsignAndVerify("_signed_user")).thenThrow(randomFrom(new RuntimeException(), new IllegalArgumentException(), new IllegalStateException()));
|
||||
|
||||
try {
|
||||
|
@ -394,32 +429,30 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testAttachIfMissingMissing() throws Exception {
|
||||
User user = new User("username", "r1", "r2");
|
||||
assertThat(message.getFromContext(InternalAuthenticationService.USER_KEY), nullValue());
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), nullValue());
|
||||
public void testAttachIfMissing() throws Exception {
|
||||
User user;
|
||||
if (randomBoolean()) {
|
||||
user = User.SYSTEM;
|
||||
} else {
|
||||
user = new User("username", "r1", "r2");
|
||||
}
|
||||
assertThat(threadContext.getTransient(InternalAuthenticationService.USER_KEY), nullValue());
|
||||
assertThat(threadContext.getHeader(InternalAuthenticationService.USER_KEY), nullValue());
|
||||
when(cryptoService.sign(InternalAuthenticationService.encodeUser(user, null))).thenReturn("_signed_user");
|
||||
service.attachUserHeaderIfMissing(message, user);
|
||||
assertThat(message.getFromContext(InternalAuthenticationService.USER_KEY), sameInstance((Object) user));
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_signed_user"));
|
||||
|
||||
user = User.SYSTEM;
|
||||
message = new InternalMessage();
|
||||
assertThat(message.getFromContext(InternalAuthenticationService.USER_KEY), nullValue());
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), nullValue());
|
||||
when(cryptoService.sign(InternalAuthenticationService.encodeUser(user, null))).thenReturn("_signed_user");
|
||||
service.attachUserHeaderIfMissing(message, user);
|
||||
assertThat(message.getFromContext(InternalAuthenticationService.USER_KEY), sameInstance((Object) user));
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_signed_user"));
|
||||
service.attachUserHeaderIfMissing(user);
|
||||
User user1 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user1, sameInstance((Object) user));
|
||||
assertThat(threadContext.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_signed_user"));
|
||||
}
|
||||
|
||||
public void testAttachIfMissingExists() throws Exception {
|
||||
User user = new User("username", "r1", "r2");
|
||||
message.putInContext(InternalAuthenticationService.USER_KEY, user);
|
||||
message.putHeader(InternalAuthenticationService.USER_KEY, "_signed_user");
|
||||
service.attachUserHeaderIfMissing(message, new User("username2", "r3", "r4"));
|
||||
assertThat(message.getFromContext(InternalAuthenticationService.USER_KEY), sameInstance((Object) user));
|
||||
assertThat(message.getHeader(InternalAuthenticationService.USER_KEY), equalTo((Object) "_signed_user"));
|
||||
threadContext.putTransient(InternalAuthenticationService.USER_KEY, user);
|
||||
threadContext.putHeader(InternalAuthenticationService.USER_KEY, "_signed_user");
|
||||
service.attachUserHeaderIfMissing(new User("username2", "r3", "r4"));
|
||||
User user1 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user1, sameInstance(user));
|
||||
assertThat(threadContext.getHeader(InternalAuthenticationService.USER_KEY), equalTo("_signed_user"));
|
||||
}
|
||||
|
||||
public void testAnonymousUserRest() throws Exception {
|
||||
|
@ -431,13 +464,14 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
}
|
||||
Settings settings = builder.build();
|
||||
AnonymousService holder = new AnonymousService(settings);
|
||||
service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, holder, new DefaultAuthenticationFailureHandler());
|
||||
service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, holder, new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
|
||||
RestRequest request = new FakeRestRequest();
|
||||
|
||||
User user = service.authenticate(request);
|
||||
assertThat(request.getFromContext(InternalAuthenticationService.USER_KEY), notNullValue());
|
||||
assertThat(request.getFromContext(InternalAuthenticationService.USER_KEY), sameInstance((Object) user));
|
||||
User user1 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user1, notNullValue());
|
||||
assertThat(user1, sameInstance((Object) user));
|
||||
assertThat(user, notNullValue());
|
||||
assertThat(user.principal(), equalTo(username));
|
||||
assertThat(user.roles(), arrayContainingInAnyOrder("r1", "r2", "r3"));
|
||||
|
@ -447,7 +481,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
Settings settings = Settings.builder()
|
||||
.putArray("shield.authc.anonymous.roles", "r1", "r2", "r3")
|
||||
.build();
|
||||
service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, new AnonymousService(settings), new DefaultAuthenticationFailureHandler());
|
||||
service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, new AnonymousService(settings), new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
|
||||
InternalMessage message = new InternalMessage();
|
||||
|
||||
|
@ -461,7 +495,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
Settings settings = Settings.builder()
|
||||
.putArray("shield.authc.anonymous.roles", "r1", "r2", "r3")
|
||||
.build();
|
||||
service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, new AnonymousService(settings), new DefaultAuthenticationFailureHandler());
|
||||
service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, new AnonymousService(settings), new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
|
||||
InternalMessage message = new InternalMessage();
|
||||
|
||||
|
@ -471,7 +505,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testRealmTokenThrowingException() throws Exception {
|
||||
when(firstRealm.token(message)).thenThrow(authenticationError("realm doesn't like tokens"));
|
||||
when(firstRealm.token(threadContext)).thenThrow(authenticationError("realm doesn't like tokens"));
|
||||
try {
|
||||
service.authenticate("_action", message, null);
|
||||
fail("exception should bubble out");
|
||||
|
@ -482,7 +516,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testRealmTokenThrowingExceptionRest() throws Exception {
|
||||
when(firstRealm.token(restRequest)).thenThrow(authenticationError("realm doesn't like tokens"));
|
||||
when(firstRealm.token(threadContext)).thenThrow(authenticationError("realm doesn't like tokens"));
|
||||
try {
|
||||
service.authenticate(restRequest);
|
||||
fail("exception should bubble out");
|
||||
|
@ -494,7 +528,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
public void testRealmSupportsMethodThrowingException() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
when(secondRealm.token(message)).thenReturn(token);
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenThrow(authenticationError("realm doesn't like supports"));
|
||||
try {
|
||||
service.authenticate("_action", message, null);
|
||||
|
@ -507,7 +541,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
public void testRealmSupportsMethodThrowingExceptionRest() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
when(secondRealm.token(restRequest)).thenReturn(token);
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenThrow(authenticationError("realm doesn't like supports"));
|
||||
try {
|
||||
service.authenticate(restRequest);
|
||||
|
@ -520,7 +554,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
public void testRealmAuthenticateThrowingException() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
when(secondRealm.token(message)).thenReturn(token);
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
when(secondRealm.authenticate(token)).thenThrow(authenticationError("realm doesn't like authenticate"));
|
||||
try {
|
||||
|
@ -534,7 +568,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
public void testRealmAuthenticateThrowingExceptionRest() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
when(secondRealm.token(restRequest)).thenReturn(token);
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
when(secondRealm.authenticate(token)).thenThrow(authenticationError("realm doesn't like authenticate"));
|
||||
try {
|
||||
|
@ -548,8 +582,8 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
public void testRealmLookupThrowingException() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
message.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as");
|
||||
when(secondRealm.token(message)).thenReturn(token);
|
||||
threadContext.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as");
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"}));
|
||||
when(secondRealm.lookupUser("run_as")).thenThrow(authenticationError("realm doesn't want to lookup"));
|
||||
|
@ -566,8 +600,8 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
public void testRealmLookupThrowingExceptionRest() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
restRequest = new FakeRestRequest(Collections.singletonMap(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as"), Collections.<String, String>emptyMap());
|
||||
when(secondRealm.token(restRequest)).thenReturn(token);
|
||||
restRequest = new FakeRestRequest(Collections.singletonMap(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as"));
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"}));
|
||||
when(secondRealm.lookupUser("run_as")).thenThrow(authenticationError("realm doesn't want to lookup"));
|
||||
|
@ -584,8 +618,8 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
public void testRunAsLookupSameRealm() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
message.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as");
|
||||
when(secondRealm.token(message)).thenReturn(token);
|
||||
threadContext.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as");
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"}));
|
||||
when(secondRealm.lookupUser("run_as")).thenReturn(new User("looked up user", new String[]{"some role"}));
|
||||
|
@ -599,13 +633,14 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
assertThat(authenticated.roles(), arrayContaining("user"));
|
||||
assertThat(authenticated.runAs().principal(), is("looked up user"));
|
||||
assertThat(authenticated.runAs().roles(), arrayContaining("some role"));
|
||||
assertThat(message.getContext().get(InternalAuthenticationService.USER_KEY), sameInstance((Object) authenticated));
|
||||
User user1 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user1, sameInstance(authenticated));
|
||||
}
|
||||
|
||||
public void testRunAsLookupSameRealmRest() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
restRequest = new FakeRestRequest(Collections.singletonMap(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as"), Collections.<String, String>emptyMap());
|
||||
when(secondRealm.token(restRequest)).thenReturn(token);
|
||||
restRequest = new FakeRestRequest(Collections.singletonMap(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as"));
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"}));
|
||||
when(secondRealm.lookupUser("run_as")).thenReturn(new User("looked up user", new String[]{"some role"}));
|
||||
|
@ -619,13 +654,14 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
assertThat(authenticated.roles(), arrayContaining("user"));
|
||||
assertThat(authenticated.runAs().principal(), is("looked up user"));
|
||||
assertThat(authenticated.runAs().roles(), arrayContaining("some role"));
|
||||
assertThat(restRequest.getContext().get(InternalAuthenticationService.USER_KEY), sameInstance((Object) authenticated));
|
||||
User user1 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user1, sameInstance(authenticated));
|
||||
}
|
||||
|
||||
public void testRunAsLookupDifferentRealm() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
message.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as");
|
||||
when(secondRealm.token(message)).thenReturn(token);
|
||||
threadContext.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as");
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"}));
|
||||
when(firstRealm.userLookupSupported()).thenReturn(true);
|
||||
|
@ -640,13 +676,14 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
assertThat(authenticated.roles(), arrayContaining("user"));
|
||||
assertThat(authenticated.runAs().principal(), is("looked up user"));
|
||||
assertThat(authenticated.runAs().roles(), arrayContaining("some role"));
|
||||
assertThat(message.getContext().get(InternalAuthenticationService.USER_KEY), sameInstance((Object) authenticated));
|
||||
User user1 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user1, sameInstance(authenticated));
|
||||
}
|
||||
|
||||
public void testRunAsLookupDifferentRealmRest() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
restRequest = new FakeRestRequest(Collections.singletonMap(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as"), Collections.<String, String>emptyMap());
|
||||
when(secondRealm.token(restRequest)).thenReturn(token);
|
||||
restRequest = new FakeRestRequest(Collections.singletonMap(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as"));
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"}));
|
||||
when(firstRealm.lookupUser("run_as")).thenReturn(new User("looked up user", new String[]{"some role"}));
|
||||
|
@ -660,13 +697,14 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
assertThat(authenticated.roles(), arrayContaining("user"));
|
||||
assertThat(authenticated.runAs().principal(), is("looked up user"));
|
||||
assertThat(authenticated.runAs().roles(), arrayContaining("some role"));
|
||||
assertThat(restRequest.getContext().get(InternalAuthenticationService.USER_KEY), sameInstance((Object) authenticated));
|
||||
User user1 = threadContext.getTransient(InternalAuthenticationService.USER_KEY);
|
||||
assertThat(user1, sameInstance(authenticated));
|
||||
}
|
||||
|
||||
public void testRunAsWithEmptyRunAsUsernameRest() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
restRequest = new FakeRestRequest(Collections.singletonMap(InternalAuthenticationService.RUN_AS_USER_HEADER, ""), Collections.<String, String>emptyMap());
|
||||
when(secondRealm.token(restRequest)).thenReturn(token);
|
||||
restRequest = new FakeRestRequest(Collections.singletonMap(InternalAuthenticationService.RUN_AS_USER_HEADER, ""));
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"}));
|
||||
when(secondRealm.userLookupSupported()).thenReturn(true);
|
||||
|
@ -682,8 +720,8 @@ public class InternalAuthenticationServiceTests extends ESTestCase {
|
|||
|
||||
public void testRunAsWithEmptyRunAsUsername() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
message.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "");
|
||||
when(secondRealm.token(message)).thenReturn(token);
|
||||
threadContext.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "");
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"}));
|
||||
when(secondRealm.userLookupSupported()).thenReturn(true);
|
||||
|
|
|
@ -6,15 +6,14 @@
|
|||
package org.elasticsearch.shield.authc;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.shield.ShieldSettingsFilter;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.authc.esusers.ESUsersRealm;
|
||||
import org.elasticsearch.shield.authc.ldap.LdapRealm;
|
||||
import org.elasticsearch.shield.license.ShieldLicenseState;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -236,12 +235,7 @@ public class RealmsTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationToken token(RestRequest request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationToken token(TransportMessage message) {
|
||||
public AuthenticationToken token(ThreadContext threadContext) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,10 @@ import org.elasticsearch.test.ShieldSettingsSource;
|
|||
import org.elasticsearch.test.rest.client.http.HttpResponse;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
|
@ -86,17 +90,19 @@ public class RunAsIntegTests extends ShieldIntegTestCase {
|
|||
|
||||
// let's run as without authorization
|
||||
try {
|
||||
client.admin().cluster().prepareHealth().putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, ShieldSettingsSource.DEFAULT_USER_NAME).get();
|
||||
client.filterWithHeader(Collections.singletonMap(InternalAuthenticationService.RUN_AS_USER_HEADER, ShieldSettingsSource.DEFAULT_USER_NAME))
|
||||
.admin().cluster().prepareHealth().get();
|
||||
fail("run as should be unauthorized for the transport client user");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
assertThat(e.getMessage(), containsString("unauthorized"));
|
||||
assertThat(e.getMessage(), containsString("run as"));
|
||||
}
|
||||
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, new SecuredString(ShieldSettingsSource.DEFAULT_PASSWORD.toCharArray())));
|
||||
headers.put(InternalAuthenticationService.RUN_AS_USER_HEADER, ShieldSettingsSource.DEFAULT_USER_NAME);
|
||||
// lets set the user
|
||||
ClusterHealthResponse response = client.admin().cluster().prepareHealth()
|
||||
.putHeader("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, new SecuredString(ShieldSettingsSource.DEFAULT_PASSWORD.toCharArray())))
|
||||
.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, ShieldSettingsSource.DEFAULT_USER_NAME).get();
|
||||
ClusterHealthResponse response = client.filterWithHeader(headers).admin().cluster().prepareHealth().get();
|
||||
assertThat(response.isTimedOut(), is(false));
|
||||
}
|
||||
}
|
||||
|
@ -134,9 +140,11 @@ public class RunAsIntegTests extends ShieldIntegTestCase {
|
|||
});
|
||||
|
||||
try {
|
||||
client.admin().cluster().prepareHealth()
|
||||
.putHeader("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, new SecuredString(ShieldSettingsSource.DEFAULT_PASSWORD.toCharArray())))
|
||||
.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "").get();
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, new SecuredString(ShieldSettingsSource.DEFAULT_PASSWORD.toCharArray())));
|
||||
headers.put(InternalAuthenticationService.RUN_AS_USER_HEADER, "");
|
||||
|
||||
client.filterWithHeader(headers).admin().cluster().prepareHealth().get();
|
||||
fail("run as header should not be allowed to be empty");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
assertThat(e.getMessage(), containsString("unable to authenticate"));
|
||||
|
@ -161,9 +169,11 @@ public class RunAsIntegTests extends ShieldIntegTestCase {
|
|||
});
|
||||
|
||||
try {
|
||||
client.admin().cluster().prepareHealth()
|
||||
.putHeader("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, new SecuredString(ShieldSettingsSource.DEFAULT_PASSWORD.toCharArray())))
|
||||
.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "idontexist").get();
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, new SecuredString(ShieldSettingsSource.DEFAULT_PASSWORD.toCharArray())));
|
||||
headers.put(InternalAuthenticationService.RUN_AS_USER_HEADER, "idontexist");
|
||||
|
||||
client.filterWithHeader(headers).admin().cluster().prepareHealth().get();
|
||||
fail("run as header should not accept non-existent users");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
assertThat(e.getMessage(), containsString("unauthorized"));
|
||||
|
|
|
@ -13,8 +13,8 @@ import org.elasticsearch.client.AdminClient;
|
|||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.ClusterAdminClient;
|
||||
import org.elasticsearch.client.IndicesAdminClient;
|
||||
import org.elasticsearch.client.support.Headers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
|
@ -118,10 +118,10 @@ public class ESUsersRealmTests extends ESTestCase {
|
|||
when(userRolesStore.roles("user1")).thenReturn(new String[]{"role1", "role2"});
|
||||
ESUsersRealm realm = new ESUsersRealm(config, userPasswdStore, userRolesStore);
|
||||
|
||||
TransportRequest request = new TransportRequest() {};
|
||||
UsernamePasswordToken.putTokenHeader(request, new UsernamePasswordToken("user1", SecuredStringTests.build("test123")));
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
UsernamePasswordToken.putTokenHeader(threadContext, new UsernamePasswordToken("user1", SecuredStringTests.build("test123")));
|
||||
|
||||
UsernamePasswordToken token = realm.token(request);
|
||||
UsernamePasswordToken token = realm.token(threadContext);
|
||||
assertThat(token, notNullValue());
|
||||
assertThat(token.principal(), equalTo("user1"));
|
||||
assertThat(token.credentials(), notNullValue());
|
||||
|
@ -178,39 +178,6 @@ public class ESUsersRealmTests extends ESTestCase {
|
|||
assertThat(user5, sameInstance(user6));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testAuthorizationHeaderIsNotCopied() throws Exception {
|
||||
RestController restController = mock(RestController.class);
|
||||
RealmConfig config = new RealmConfig("esusers-test", Settings.EMPTY, globalSettings);
|
||||
new ESUsersRealm(config, new UserPasswdStore(config), new UserRolesStore(config));
|
||||
when(restController.relevantHeaders()).thenReturn(emptySet());
|
||||
when(client.admin()).thenReturn(adminClient);
|
||||
when(client.settings()).thenReturn(Settings.EMPTY);
|
||||
when(client.headers()).thenReturn(Headers.EMPTY);
|
||||
when(adminClient.cluster()).thenReturn(mock(ClusterAdminClient.class));
|
||||
when(adminClient.indices()).thenReturn(mock(IndicesAdminClient.class));
|
||||
final ActionRequest request = new ActionRequest() {
|
||||
@Override
|
||||
public ActionRequestValidationException validate() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
RestRequest restRequest = mock(RestRequest.class);
|
||||
final Action<ActionRequest, ?, ?> action = mock(Action.class);
|
||||
final ActionListener listener = mock(ActionListener.class);
|
||||
BaseRestHandler handler = new BaseRestHandler(Settings.EMPTY, restController, client) {
|
||||
@Override
|
||||
protected void handleRequest(RestRequest restRequest, RestChannel channel, Client client) throws Exception {
|
||||
client.execute(action, request, listener);
|
||||
}
|
||||
};
|
||||
|
||||
when(restRequest.header(UsernamePasswordToken.BASIC_AUTH_HEADER)).thenReturn("foobar");
|
||||
RestChannel channel = mock(RestChannel.class);
|
||||
handler.handleRequest(restRequest, channel);
|
||||
assertThat(request.getHeader(UsernamePasswordToken.BASIC_AUTH_HEADER), is(nullValue()));
|
||||
}
|
||||
|
||||
static class UserPasswdStore extends FileUserPasswdStore {
|
||||
public UserPasswdStore(RealmConfig config) {
|
||||
super(config, mock(ResourceWatcherService.class));
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
package org.elasticsearch.shield.authc.pki;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.authc.RealmConfig;
|
||||
import org.elasticsearch.shield.authc.support.DnRoleMapper;
|
||||
|
@ -14,7 +14,6 @@ import org.elasticsearch.shield.authc.support.SecuredString;
|
|||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.shield.support.NoOpLogger;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.rest.FakeRestRequest;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.junit.Before;
|
||||
|
||||
|
@ -53,25 +52,13 @@ public class PkiRealmTests extends ESTestCase {
|
|||
assertThat(realm.supports(new X509AuthenticationToken(new X509Certificate[0], "", "")), is(true));
|
||||
}
|
||||
|
||||
public void testExtractTokenFromRestRequest() throws Exception {
|
||||
public void testExtractToken() throws Exception {
|
||||
X509Certificate certificate = readCert(getDataPath("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.cert"));
|
||||
RestRequest restRequest = new FakeRestRequest();
|
||||
restRequest.putInContext(PkiRealm.PKI_CERT_HEADER_NAME, new X509Certificate[] { certificate });
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
threadContext.putTransient(PkiRealm.PKI_CERT_HEADER_NAME, new X509Certificate[] { certificate });
|
||||
PkiRealm realm = new PkiRealm(new RealmConfig("", Settings.EMPTY, globalSettings), mock(DnRoleMapper.class));
|
||||
|
||||
X509AuthenticationToken token = realm.token(restRequest);
|
||||
assertThat(token, is(notNullValue()));
|
||||
assertThat(token.dn(), is("CN=Elasticsearch Test Node, OU=elasticsearch, O=org"));
|
||||
assertThat(token.principal(), is("Elasticsearch Test Node"));
|
||||
}
|
||||
|
||||
public void testExtractTokenFromTransportMessage() throws Exception {
|
||||
X509Certificate certificate = readCert(getDataPath("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.cert"));
|
||||
Message message = new Message();
|
||||
message.putInContext(PkiRealm.PKI_CERT_HEADER_NAME, new X509Certificate[]{certificate});
|
||||
PkiRealm realm = new PkiRealm(new RealmConfig("", Settings.EMPTY, globalSettings), mock(DnRoleMapper.class));
|
||||
|
||||
X509AuthenticationToken token = realm.token(message);
|
||||
X509AuthenticationToken token = realm.token(threadContext);
|
||||
assertThat(token, is(notNullValue()));
|
||||
assertThat(token.dn(), is("CN=Elasticsearch Test Node, OU=elasticsearch, O=org"));
|
||||
assertThat(token.principal(), is("Elasticsearch Test Node"));
|
||||
|
@ -96,10 +83,10 @@ public class PkiRealmTests extends ESTestCase {
|
|||
DnRoleMapper roleMapper = mock(DnRoleMapper.class);
|
||||
PkiRealm realm = new PkiRealm(new RealmConfig("", Settings.builder().put("username_pattern", "OU=(.*?),").build(), globalSettings), roleMapper);
|
||||
when(roleMapper.resolveRoles(anyString(), anyList())).thenReturn(Collections.<String>emptySet());
|
||||
FakeRestRequest restRequest = new FakeRestRequest();
|
||||
restRequest.putInContext(PkiRealm.PKI_CERT_HEADER_NAME, new X509Certificate[] { certificate });
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
threadContext.putTransient(PkiRealm.PKI_CERT_HEADER_NAME, new X509Certificate[] { certificate });
|
||||
|
||||
X509AuthenticationToken token = realm.token(restRequest);
|
||||
X509AuthenticationToken token = realm.token(threadContext);
|
||||
User user = realm.authenticate(token);
|
||||
assertThat(user, is(notNullValue()));
|
||||
assertThat(user.principal(), is("elasticsearch"));
|
||||
|
@ -117,10 +104,10 @@ public class PkiRealmTests extends ESTestCase {
|
|||
PkiRealm realm = new PkiRealm(new RealmConfig("", settings, globalSettings), roleMapper);
|
||||
when(roleMapper.resolveRoles(anyString(), anyList())).thenReturn(Collections.<String>emptySet());
|
||||
|
||||
FakeRestRequest restRequest = new FakeRestRequest();
|
||||
restRequest.putInContext(PkiRealm.PKI_CERT_HEADER_NAME, new X509Certificate[] { certificate });
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
threadContext.putTransient(PkiRealm.PKI_CERT_HEADER_NAME, new X509Certificate[] { certificate });
|
||||
|
||||
X509AuthenticationToken token = realm.token(restRequest);
|
||||
X509AuthenticationToken token = realm.token(threadContext);
|
||||
User user = realm.authenticate(token);
|
||||
assertThat(user, is(notNullValue()));
|
||||
assertThat(user.principal(), is("Elasticsearch Test Node"));
|
||||
|
@ -138,10 +125,10 @@ public class PkiRealmTests extends ESTestCase {
|
|||
PkiRealm realm = new PkiRealm(new RealmConfig("", settings, globalSettings), roleMapper);
|
||||
when(roleMapper.resolveRoles(anyString(), anyList())).thenReturn(Collections.<String>emptySet());
|
||||
|
||||
FakeRestRequest restRequest = new FakeRestRequest();
|
||||
restRequest.putInContext(PkiRealm.PKI_CERT_HEADER_NAME, new X509Certificate[] { certificate });
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
threadContext.putTransient(PkiRealm.PKI_CERT_HEADER_NAME, new X509Certificate[] { certificate });
|
||||
|
||||
X509AuthenticationToken token = realm.token(restRequest);
|
||||
X509AuthenticationToken token = realm.token(threadContext);
|
||||
User user = realm.authenticate(token);
|
||||
assertThat(user, is(nullValue()));
|
||||
}
|
||||
|
|
|
@ -7,9 +7,10 @@ package org.elasticsearch.shield.authc.support;
|
|||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.common.Base64;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
|
@ -31,9 +32,9 @@ public class UsernamePasswordTokenTests extends ESTestCase {
|
|||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
public void testPutToken() throws Exception {
|
||||
TransportRequest request = new TransportRequest() {};
|
||||
UsernamePasswordToken.putTokenHeader(request, new UsernamePasswordToken("user1", SecuredStringTests.build("test123")));
|
||||
String header = request.getHeader(UsernamePasswordToken.BASIC_AUTH_HEADER);
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
UsernamePasswordToken.putTokenHeader(threadContext, new UsernamePasswordToken("user1", SecuredStringTests.build("test123")));
|
||||
String header = threadContext.getHeader(UsernamePasswordToken.BASIC_AUTH_HEADER);
|
||||
assertThat(header, notNullValue());
|
||||
assertTrue(header.startsWith("Basic "));
|
||||
String token = header.substring("Basic ".length());
|
||||
|
@ -47,10 +48,10 @@ public class UsernamePasswordTokenTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testExtractToken() throws Exception {
|
||||
TransportRequest request = new TransportRequest() {};
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
String header = "Basic " + Base64.encodeBytes("user1:test123".getBytes(StandardCharsets.UTF_8));
|
||||
request.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, header);
|
||||
UsernamePasswordToken token = UsernamePasswordToken.extractToken(request, null);
|
||||
threadContext.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, header);
|
||||
UsernamePasswordToken token = UsernamePasswordToken.extractToken(threadContext, null);
|
||||
assertThat(token, notNullValue());
|
||||
assertThat(token.principal(), equalTo("user1"));
|
||||
assertThat(new String(token.credentials().internalChars()), equalTo("test123"));
|
||||
|
@ -59,10 +60,10 @@ public class UsernamePasswordTokenTests extends ESTestCase {
|
|||
public void testExtractTokenInvalid() throws Exception {
|
||||
String[] invalidValues = { "Basic", "Basic ", "Basic f" };
|
||||
for (String value : invalidValues) {
|
||||
TransportRequest request = new TransportRequest() {};
|
||||
request.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, value);
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
threadContext.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, value);
|
||||
try {
|
||||
UsernamePasswordToken.extractToken(request, null);
|
||||
UsernamePasswordToken.extractToken(threadContext, null);
|
||||
fail("Expected an authentication exception for invalid basic auth token [" + value + "]");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
// expected
|
||||
|
@ -72,11 +73,11 @@ public class UsernamePasswordTokenTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testThatAuthenticationExceptionContainsResponseHeaders() {
|
||||
TransportRequest request = new TransportRequest() {};
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
String header = "BasicBroken";
|
||||
request.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, header);
|
||||
threadContext.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, header);
|
||||
try {
|
||||
UsernamePasswordToken.extractToken(request, null);
|
||||
UsernamePasswordToken.extractToken(threadContext, null);
|
||||
fail("Expected exception but did not happen");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
assertAuthenticationException(e);
|
||||
|
|
|
@ -10,6 +10,8 @@ import org.elasticsearch.shield.authc.support.Hasher;
|
|||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.BASIC_AUTH_HEADER;
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.test.ShieldTestsUtils.assertAuthorizationException;
|
||||
|
@ -51,21 +53,21 @@ public class AnalyzeTests extends ShieldIntegTestCase {
|
|||
ensureGreen();
|
||||
|
||||
//ok: user has permissions for analyze on test_*
|
||||
client().admin().indices().prepareAnalyze("this is my text").setIndex("test_1").setAnalyzer("standard")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("analyze_indices", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("analyze_indices", new SecuredString("test123".toCharArray()))))
|
||||
.admin().indices().prepareAnalyze("this is my text").setIndex("test_1").setAnalyzer("standard").get();
|
||||
|
||||
try {
|
||||
//fails: user doesn't have permissions for analyze on index non_authorized
|
||||
client().admin().indices().prepareAnalyze("this is my text").setIndex("non_authorized").setAnalyzer("standard")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("analyze_indices", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("analyze_indices", new SecuredString("test123".toCharArray()))))
|
||||
.admin().indices().prepareAnalyze("this is my text").setIndex("non_authorized").setAnalyzer("standard").get();
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/analyze] is unauthorized for user [analyze_indices]"));
|
||||
}
|
||||
|
||||
try {
|
||||
//fails: user doesn't have permissions for cluster level analyze
|
||||
client().admin().indices().prepareAnalyze("this is my text").setAnalyzer("standard")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("analyze_indices", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("analyze_indices", new SecuredString("test123".toCharArray()))))
|
||||
.admin().indices().prepareAnalyze("this is my text").setAnalyzer("standard").get();
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [cluster:admin/analyze] is unauthorized for user [analyze_indices]"));
|
||||
}
|
||||
|
@ -76,13 +78,13 @@ public class AnalyzeTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: user doesn't have permissions for analyze on index test_1
|
||||
client().admin().indices().prepareAnalyze("this is my text").setIndex("test_1").setAnalyzer("standard")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("analyze_cluster", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("analyze_cluster", new SecuredString("test123".toCharArray()))))
|
||||
.admin().indices().prepareAnalyze("this is my text").setIndex("test_1").setAnalyzer("standard").get();
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/analyze] is unauthorized for user [analyze_cluster]"));
|
||||
}
|
||||
|
||||
client().admin().indices().prepareAnalyze("this is my text").setAnalyzer("standard")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("analyze_cluster", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("analyze_cluster", new SecuredString("test123".toCharArray()))))
|
||||
.admin().indices().prepareAnalyze("this is my text").setAnalyzer("standard").get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,16 @@ import org.elasticsearch.action.admin.indices.alias.Alias;
|
|||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.index.IndexNotFoundException;
|
||||
import org.elasticsearch.shield.authc.support.Hasher;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.BASIC_AUTH_HEADER;
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.test.ShieldTestsUtils.assertAuthorizationException;
|
||||
|
@ -85,20 +89,18 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
public void testCreateIndexThenAliasesCreateOnlyPermission() {
|
||||
//user has create permission only: allows to create indices, manage_aliases is required to add/remove aliases
|
||||
assertAcked(client().admin().indices().prepareCreate("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))));
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray())));
|
||||
assertAcked(client().filterWithHeader(headers).admin().indices().prepareCreate("test_1").get());
|
||||
|
||||
try {
|
||||
client().admin().indices().prepareAliases().addAlias("test_1", "test_alias")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareAliases().addAlias("test_1", "test_alias").get();
|
||||
fail("add alias should have failed due to missing manage_aliases privileges");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_only]"));
|
||||
}
|
||||
|
||||
try {
|
||||
client().admin().indices().prepareAliases().addAlias("test_*", "test_alias")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareAliases().addAlias("test_*", "test_alias").get();
|
||||
fail("add alias should have failed due to missing manage_aliases privileges");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[test_*]"));
|
||||
|
@ -107,9 +109,9 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
public void testCreateIndexAndAliasesCreateOnlyPermission() {
|
||||
//user has create permission only: allows to create indices, manage_aliases is required to add aliases although they are part of the same create index request
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray())));
|
||||
try {
|
||||
client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_2"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareCreate("test_1").addAlias(new Alias("test_2")).get();
|
||||
fail("create index should have failed due to missing manage_aliases privileges");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_only]"));
|
||||
|
@ -118,25 +120,23 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
public void testDeleteAliasesCreateOnlyPermission() {
|
||||
//user has create permission only: allows to create indices, manage_aliases is required to add/remove aliases
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray())));
|
||||
try {
|
||||
client().admin().indices().prepareAliases().removeAlias("test_1", "alias_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareAliases().removeAlias("test_1", "alias_1").get();
|
||||
fail("remove alias should have failed due to missing manage_aliases privileges");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_only]"));
|
||||
}
|
||||
|
||||
try {
|
||||
client().admin().indices().prepareAliases().removeAlias("test_1", "alias_*")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareAliases().removeAlias("test_1", "alias_*").get();
|
||||
fail("remove alias should have failed due to missing manage_aliases privileges");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[alias_*"));
|
||||
}
|
||||
|
||||
try {
|
||||
client().admin().indices().prepareAliases().removeAlias("test_1", "_all")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareAliases().removeAlias("test_1", "_all").get();
|
||||
fail("remove alias should have failed due to missing manage_aliases privileges");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[_all]"));
|
||||
|
@ -145,41 +145,37 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
public void testGetAliasesCreateOnlyPermission() {
|
||||
//user has create permission only: allows to create indices, manage_aliases is required to retrieve aliases though
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray())));
|
||||
try {
|
||||
client().admin().indices().prepareGetAliases("test_1").setIndices("test_1").setIndicesOptions(IndicesOptions.lenientExpandOpen())
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareGetAliases("test_1").setIndices("test_1").setIndicesOptions(IndicesOptions.lenientExpandOpen()).get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases/get] is unauthorized for user [create_only]"));
|
||||
}
|
||||
|
||||
try {
|
||||
client().admin().indices().prepareGetAliases("_all").setIndices("test_1").setIndicesOptions(IndicesOptions.lenientExpandOpen())
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareGetAliases("_all").setIndices("test_1").setIndicesOptions(IndicesOptions.lenientExpandOpen()).get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[_all]"));
|
||||
}
|
||||
|
||||
try {
|
||||
client().admin().indices().prepareGetAliases().setIndices("test_1").setIndicesOptions(IndicesOptions.lenientExpandOpen())
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareGetAliases().setIndices("test_1").setIndicesOptions(IndicesOptions.lenientExpandOpen()).get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[_all]"));
|
||||
}
|
||||
|
||||
try {
|
||||
client().admin().indices().prepareGetAliases("test_alias").setIndices("test_*").setIndicesOptions(IndicesOptions.lenientExpandOpen())
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareGetAliases("test_alias").setIndices("test_*").setIndicesOptions(IndicesOptions.lenientExpandOpen()).get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[test_*]"));
|
||||
}
|
||||
|
||||
try {
|
||||
client().admin().indices().prepareGetAliases()
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareGetAliases().get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[_all]"));
|
||||
|
@ -188,21 +184,19 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
public void testCreateIndexThenAliasesCreateAndAliasesPermission() {
|
||||
//user has create and manage_aliases permission on test_*. manage_aliases is required to add/remove aliases on both aliases and indices
|
||||
assertAcked(client().admin().indices().prepareCreate("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray())));
|
||||
|
||||
assertAcked(client().filterWithHeader(headers).admin().indices().prepareCreate("test_1").get());
|
||||
|
||||
//ok: user has manage_aliases on test_*
|
||||
assertAcked(client().admin().indices().prepareAliases().addAlias("test_1", "test_alias")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client().filterWithHeader(headers).admin().indices().prepareAliases().addAlias("test_1", "test_alias").get());
|
||||
|
||||
//ok: user has manage_aliases on test_*
|
||||
assertAcked(client().admin().indices().prepareAliases().addAlias("test_*", "test_alias_2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client().filterWithHeader(headers).admin().indices().prepareAliases().addAlias("test_*", "test_alias_2").get());
|
||||
|
||||
try {
|
||||
//fails: user doesn't have manage_aliases on alias_1
|
||||
client().admin().indices().prepareAliases().addAlias("test_1", "alias_1").addAlias("test_1", "test_alias")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareAliases().addAlias("test_1", "alias_1").addAlias("test_1", "test_alias").get();
|
||||
fail("add alias should have failed due to missing manage_aliases privileges on alias_1");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_test]"));
|
||||
|
@ -212,13 +206,12 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
public void testCreateIndexAndAliasesCreateAndAliasesPermission() {
|
||||
//user has create and manage_aliases permission on test_*. manage_aliases is required to add/remove aliases on both aliases and indices
|
||||
//ok: user has manage_aliases on test_*
|
||||
assertAcked(client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray())));
|
||||
assertAcked(client().filterWithHeader(headers).admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")).get());
|
||||
|
||||
try {
|
||||
//fails: user doesn't have manage_aliases on alias_1
|
||||
client().admin().indices().prepareCreate("test_2").addAlias(new Alias("test_alias")).addAlias(new Alias("alias_2"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareCreate("test_2").addAlias(new Alias("test_alias")).addAlias(new Alias("alias_2")).get();
|
||||
fail("create index should have failed due to missing manage_aliases privileges on alias_2");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_test]"));
|
||||
|
@ -228,23 +221,20 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
public void testDeleteAliasesCreateAndAliasesPermission() {
|
||||
//user has create and manage_aliases permission on test_*. manage_aliases is required to add/remove aliases on both aliases and indices
|
||||
//ok: user has manage_aliases on test_*
|
||||
assertAcked(client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias_1")).addAlias(new Alias("test_alias_2"))
|
||||
.addAlias(new Alias("test_alias_3")).addAlias(new Alias("test_alias_4"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray())));
|
||||
|
||||
assertAcked(client().filterWithHeader(headers).admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias_1")).addAlias(new Alias("test_alias_2"))
|
||||
.addAlias(new Alias("test_alias_3")).addAlias(new Alias("test_alias_4")).get());
|
||||
//ok: user has manage_aliases on test_*
|
||||
assertAcked(client().admin().indices().prepareAliases().removeAlias("test_1", "test_alias_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client().filterWithHeader(headers).admin().indices().prepareAliases().removeAlias("test_1", "test_alias_1").get());
|
||||
//ok: user has manage_aliases on test_*
|
||||
assertAcked(client().admin().indices().prepareAliases().removeAlias("test_*", "test_alias_2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client().filterWithHeader(headers).admin().indices().prepareAliases().removeAlias("test_*", "test_alias_2").get());
|
||||
//ok: user has manage_aliases on test_*
|
||||
assertAcked(client().admin().indices().prepareAliases().removeAlias("test_1", "test_alias_*")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client().filterWithHeader(headers).admin().indices().prepareAliases().removeAlias("test_1", "test_alias_*").get());
|
||||
|
||||
try {
|
||||
//fails: all aliases have been deleted, no existing aliases match test_alias_*
|
||||
client().admin().indices().prepareAliases().removeAlias("test_1", "test_alias_*")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareAliases().removeAlias("test_1", "test_alias_*").get();
|
||||
fail("remove alias should have failed due to no existing matching aliases to expand test_alias_* to");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[test_alias_*]"));
|
||||
|
@ -252,8 +242,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: all aliases have been deleted, no existing aliases match _all
|
||||
client().admin().indices().prepareAliases().removeAlias("test_1", "_all")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareAliases().removeAlias("test_1", "_all").get();
|
||||
fail("remove alias should have failed due to no existing matching aliases to expand _all to");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[_all]"));
|
||||
|
@ -261,8 +250,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: user doesn't have manage_aliases on alias_1
|
||||
client().admin().indices().prepareAliases().removeAlias("test_1", "alias_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareAliases().removeAlias("test_1", "alias_1").get();
|
||||
fail("remove alias should have failed due to missing manage_aliases privileges on alias_1");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_test]"));
|
||||
|
@ -270,8 +258,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: user doesn't have manage_aliases on alias_1
|
||||
client().admin().indices().prepareAliases().removeAlias("test_1", new String[]{"_all", "alias_1"})
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(headers).admin().indices().prepareAliases().removeAlias("test_1", new String[]{"_all", "alias_1"}).get();
|
||||
fail("remove alias should have failed due to missing manage_aliases privileges on alias_1");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_test]"));
|
||||
|
@ -280,54 +267,45 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
public void testGetAliasesCreateAndAliasesPermission() {
|
||||
//user has create and manage_aliases permission on test_*. manage_aliases is required to retrieve aliases on both aliases and indices
|
||||
|
||||
assertAcked(client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray())));
|
||||
final Client client = client().filterWithHeader(headers);
|
||||
assertAcked(client.admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")).get());
|
||||
|
||||
//ok: user has manage_aliases on test_*
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("test_alias").setIndices("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("test_alias").setIndices("test_1"),
|
||||
"test_1", "test_alias");
|
||||
|
||||
//ok: user has manage_aliases on test_*, test_* gets resolved to test_1
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("test_alias").setIndices("test_*")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("test_alias").setIndices("test_*"),
|
||||
"test_1", "test_alias");
|
||||
|
||||
//ok: user has manage_aliases on test_*, empty indices gets resolved to _all indices (thus test_1)
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("test_alias")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("test_alias"),
|
||||
"test_1", "test_alias");
|
||||
|
||||
//ok: user has manage_aliases on test_*, _all aliases gets resolved to test_alias and empty indices gets resolved to _all indices (thus test_1)
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("_all").setIndices("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("_all").setIndices("test_1"),
|
||||
"test_1", "test_alias");
|
||||
|
||||
//ok: user has manage_aliases on test_*, empty aliases gets resolved to test_alias and empty indices gets resolved to _all indices (thus test_1)
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setIndices("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setIndices("test_1"),
|
||||
"test_1", "test_alias");
|
||||
|
||||
//ok: user has manage_aliases on test_*, test_* aliases gets resolved to test_alias and empty indices gets resolved to _all indices (thus test_1)
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("test_*").setIndices("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("test_*").setIndices("test_1"),
|
||||
"test_1", "test_alias");
|
||||
|
||||
//ok: user has manage_aliases on test_*, _all aliases gets resolved to test_alias and _all indices becomes test_1
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("_all").setIndices("_all")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("_all").setIndices("_all"),
|
||||
"test_1", "test_alias");
|
||||
|
||||
//ok: user has manage_aliases on test_*, empty aliases gets resolved to test_alias and empty indices becomes test_1
|
||||
assertAliases(client().admin().indices().prepareGetAliases()
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases(),
|
||||
"test_1", "test_alias");
|
||||
|
||||
try {
|
||||
//fails: user has manage_aliases on test_*, although _all aliases and empty indices can be resolved, the explicit non authorized alias (alias_1) causes the request to fail
|
||||
client().admin().indices().prepareGetAliases().setAliases("_all", "alias_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareGetAliases().setAliases("_all", "alias_1").get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges on alias_1");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases/get] is unauthorized for user [create_test_aliases_test]"));
|
||||
|
@ -335,8 +313,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: user doesn't have manage_aliases on alias_1
|
||||
client().admin().indices().prepareGetAliases().setAliases("alias_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareGetAliases().setAliases("alias_1").get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges on alias_1");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases/get] is unauthorized for user [create_test_aliases_test]"));
|
||||
|
@ -344,14 +321,15 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
public void testCreateIndexThenAliasesCreateAndAliasesPermission2() {
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray())));
|
||||
final Client client = client().filterWithHeader(headers);
|
||||
|
||||
//user has create permission on test_* and manage_aliases permission on alias_*. manage_aliases is required to add/remove aliases on both aliases and indices
|
||||
assertAcked(client().admin().indices().prepareCreate("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client.admin().indices().prepareCreate("test_1"));
|
||||
|
||||
try {
|
||||
//fails: user doesn't have manage aliases on test_1
|
||||
client().admin().indices().prepareAliases().addAlias("test_1", "test_alias")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareAliases().addAlias("test_1", "test_alias").get();
|
||||
fail("add alias should have failed due to missing manage_aliases privileges on test_alias and test_1");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
|
||||
|
@ -359,8 +337,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: user doesn't have manage aliases on test_1
|
||||
client().admin().indices().prepareAliases().addAlias("test_1", "alias_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareAliases().addAlias("test_1", "alias_1").get();
|
||||
fail("add alias should have failed due to missing manage_aliases privileges on test_1");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
|
||||
|
@ -368,8 +345,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: user doesn't have manage aliases on test_*, no matching indices to replace wildcards
|
||||
client().admin().indices().prepareAliases().addAlias("test_*", "alias_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareAliases().addAlias("test_*", "alias_1").get();
|
||||
fail("add alias should have failed due to missing manage_aliases privileges on test_1");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[test_*]"));
|
||||
|
@ -377,11 +353,13 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
public void testCreateIndexAndAliasesCreateAndAliasesPermission2() {
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray())));
|
||||
final Client client = client().filterWithHeader(headers);
|
||||
|
||||
//user has create permission on test_* and manage_aliases permission on alias_*. manage_aliases is required to add/remove aliases on both aliases and indices
|
||||
try {
|
||||
//fails: user doesn't have manage_aliases on test_1, create index is rejected as a whole
|
||||
client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")).get();
|
||||
fail("create index should have failed due to missing manage_aliases privileges on test_1 and test_alias");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
|
||||
|
@ -389,8 +367,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: user doesn't have manage_aliases on test_*, create index is rejected as a whole
|
||||
client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")).addAlias(new Alias("alias_1"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")).addAlias(new Alias("alias_1")).get();
|
||||
fail("create index should have failed due to missing manage_aliases privileges on test_1 and test_alias");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
|
||||
|
@ -398,11 +375,13 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
public void testDeleteAliasesCreateAndAliasesPermission2() {
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray())));
|
||||
final Client client = client().filterWithHeader(headers);
|
||||
|
||||
//user has create permission on test_* and manage_aliases permission on alias_*. manage_aliases is required to add/remove aliases on both aliases and indices
|
||||
try {
|
||||
//fails: user doesn't have manage_aliases on test_1
|
||||
client().admin().indices().prepareAliases().removeAlias("test_1", "test_alias")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareAliases().removeAlias("test_1", "test_alias").get();
|
||||
fail("remove alias should have failed due to missing manage_aliases privileges on test_alias and test_1");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
|
||||
|
@ -410,8 +389,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: user doesn't have manage_aliases on test_1
|
||||
client().admin().indices().prepareAliases().removeAlias("test_1", "alias_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareAliases().removeAlias("test_1", "alias_1").get();
|
||||
fail("remove alias should have failed due to missing manage_aliases privileges on test_1");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
|
||||
|
@ -419,8 +397,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: user doesn't have manage_aliases on test_*, wildcards can't get replaced
|
||||
client().admin().indices().prepareAliases().removeAlias("test_*", "alias_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareAliases().removeAlias("test_*", "alias_1").get();
|
||||
fail("remove alias should have failed due to missing manage_aliases privileges on test_*");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[test_*]"));
|
||||
|
@ -428,14 +405,15 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
public void testGetAliasesCreateAndAliasesPermission2() {
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray())));
|
||||
final Client client = client().filterWithHeader(headers);
|
||||
|
||||
//user has create permission on test_* and manage_aliases permission on alias_*. manage_aliases is required to retrieve aliases on both aliases and indices
|
||||
assertAcked(client().admin().indices().prepareCreate("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client.admin().indices().prepareCreate("test_1"));
|
||||
|
||||
try {
|
||||
//fails: user doesn't have manage aliases on test_1, nor test_alias
|
||||
client().admin().indices().prepareGetAliases().setAliases("test_alias").setIndices("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareGetAliases().setAliases("test_alias").setIndices("test_1").get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges on test_alias and test_1");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases/get] is unauthorized for user [create_test_aliases_alias]"));
|
||||
|
@ -443,8 +421,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: user doesn't have manage aliases on test_*, no matching indices to replace wildcards
|
||||
client().admin().indices().prepareGetAliases().setIndices("test_*").setAliases("test_alias")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareGetAliases().setIndices("test_*").setAliases("test_alias").get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges on test_*");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[test_*]"));
|
||||
|
@ -452,8 +429,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: no existing indices to replace empty indices (thus _all)
|
||||
client().admin().indices().prepareGetAliases().setAliases("test_alias")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareGetAliases().setAliases("test_alias").get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges on any index");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[_all]"));
|
||||
|
@ -461,8 +437,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: no existing aliases to replace wildcards
|
||||
client().admin().indices().prepareGetAliases().setIndices("test_1").setAliases("test_*")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareGetAliases().setIndices("test_1").setAliases("test_*").get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges on test_1");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[test_*]"));
|
||||
|
@ -470,8 +445,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: no existing aliases to replace _all
|
||||
client().admin().indices().prepareGetAliases().setIndices("test_1").setAliases("_all")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareGetAliases().setIndices("test_1").setAliases("_all").get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges on test_1");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[_all]"));
|
||||
|
@ -479,8 +453,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: no existing aliases to replace empty aliases
|
||||
client().admin().indices().prepareGetAliases().setIndices("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareGetAliases().setIndices("test_1").get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges on test_1");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[_all]"));
|
||||
|
@ -488,8 +461,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
|
||||
try {
|
||||
//fails: no existing aliases to replace empty aliases
|
||||
client().admin().indices().prepareGetAliases()
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareGetAliases().get();
|
||||
fail("get alias should have failed due to missing manage_aliases privileges on test_1");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[_all]"));
|
||||
|
@ -497,55 +469,52 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
public void testCreateIndexThenAliasesCreateAndAliasesPermission3() {
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray())));
|
||||
final Client client = client().filterWithHeader(headers);
|
||||
|
||||
//user has create permission on test_* and manage_aliases permission on test_*,alias_*. All good.
|
||||
assertAcked(client().admin().indices().prepareCreate("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client.admin().indices().prepareCreate("test_1"));
|
||||
|
||||
assertAcked(client().admin().indices().prepareAliases().addAlias("test_1", "test_alias")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client.admin().indices().prepareAliases().addAlias("test_1", "test_alias"));
|
||||
|
||||
assertAcked(client().admin().indices().prepareAliases().addAlias("test_1", "alias_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client.admin().indices().prepareAliases().addAlias("test_1", "alias_1"));
|
||||
|
||||
assertAcked(client().admin().indices().prepareAliases().addAlias("test_*", "alias_2")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client.admin().indices().prepareAliases().addAlias("test_*", "alias_2"));
|
||||
}
|
||||
|
||||
public void testCreateIndexAndAliasesCreateAndAliasesPermission3() {
|
||||
//user has create permission on test_* and manage_aliases permission on test_*,alias_*. All good.
|
||||
assertAcked(client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray())));
|
||||
final Client client = client().filterWithHeader(headers);
|
||||
|
||||
assertAcked(client().admin().indices().prepareCreate("test_2").addAlias(new Alias("test_alias_2")).addAlias(new Alias("alias_2"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
|
||||
//user has create permission on test_* and manage_aliases permission on test_*,alias_*. All good.
|
||||
assertAcked(client.admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")));
|
||||
|
||||
assertAcked(client.admin().indices().prepareCreate("test_2").addAlias(new Alias("test_alias_2")).addAlias(new Alias("alias_2")));
|
||||
}
|
||||
|
||||
public void testDeleteAliasesCreateAndAliasesPermission3() {
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray())));
|
||||
final Client client = client().filterWithHeader(headers);
|
||||
|
||||
//user has create permission on test_* and manage_aliases permission on test_*,alias_*. All good.
|
||||
assertAcked(client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")).addAlias(new Alias("alias_1"))
|
||||
.addAlias(new Alias("alias_2")).addAlias(new Alias("alias_3"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client.admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")).addAlias(new Alias("alias_1"))
|
||||
.addAlias(new Alias("alias_2")).addAlias(new Alias("alias_3")));
|
||||
|
||||
try {
|
||||
//fails: user doesn't have manage_aliases privilege on non_authorized
|
||||
client().admin().indices().prepareAliases().removeAlias("test_1", "non_authorized").removeAlias("test_1", "test_alias")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareAliases().removeAlias("test_1", "non_authorized").removeAlias("test_1", "test_alias").get();
|
||||
fail("remove alias should have failed due to missing manage_aliases privileges on non_authorized");
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_test_alias]"));
|
||||
}
|
||||
|
||||
assertAcked(client().admin().indices().prepareAliases().removeAlias("test_1", "alias_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
|
||||
|
||||
assertAcked(client().admin().indices().prepareAliases().removeAlias("test_*", "_all")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client.admin().indices().prepareAliases().removeAlias("test_1", "alias_1"));
|
||||
|
||||
assertAcked(client.admin().indices().prepareAliases().removeAlias("test_*", "_all"));
|
||||
|
||||
try {
|
||||
//fails: all aliases have been deleted, _all can't be resolved to any existing authorized aliases
|
||||
client().admin().indices().prepareAliases().removeAlias("test_1", "_all")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareAliases().removeAlias("test_1", "_all").get();
|
||||
fail("remove alias should have failed due to no existing aliases matching _all");
|
||||
} catch(IndexNotFoundException e) {
|
||||
assertThat(e.toString(), containsString("[_all]"));
|
||||
|
@ -553,51 +522,43 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
public void testGetAliasesCreateAndAliasesPermission3() {
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray())));
|
||||
final Client client = client().filterWithHeader(headers);
|
||||
|
||||
//user has create permission on test_* and manage_aliases permission on test_*,alias_*. All good.
|
||||
assertAcked(client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")).addAlias(new Alias("alias_1"))
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
|
||||
assertAcked(client.admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")).addAlias(new Alias("alias_1")));
|
||||
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("test_alias").setIndices("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("test_alias").setIndices("test_1"),
|
||||
"test_1", "test_alias");
|
||||
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("alias_1").setIndices("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("alias_1").setIndices("test_1"),
|
||||
"test_1", "alias_1");
|
||||
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("alias_1").setIndices("test_*")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("alias_1").setIndices("test_*"),
|
||||
"test_1", "alias_1");
|
||||
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("test_*").setIndices("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("test_*").setIndices("test_1"),
|
||||
"test_1", "test_alias");
|
||||
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("_all").setIndices("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("_all").setIndices("test_1"),
|
||||
"test_1", "alias_1", "test_alias");
|
||||
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("_all")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("_all"),
|
||||
"test_1", "alias_1", "test_alias");
|
||||
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setIndices("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setIndices("test_1"),
|
||||
"test_1", "alias_1", "test_alias");
|
||||
|
||||
assertAliases(client().admin().indices().prepareGetAliases()
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))),
|
||||
"test_1", "alias_1", "test_alias");
|
||||
assertAliases(client.admin().indices().prepareGetAliases(), "test_1", "alias_1", "test_alias");
|
||||
|
||||
assertAliases(client().admin().indices().prepareGetAliases().setAliases("alias_*").setIndices("test_*")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))),
|
||||
assertAliases(client.admin().indices().prepareGetAliases().setAliases("alias_*").setIndices("test_*"),
|
||||
"test_1", "alias_1");
|
||||
}
|
||||
|
||||
public void testCreateIndexAliasesOnlyPermission() {
|
||||
try {
|
||||
client().admin().indices().prepareCreate("test_1")
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("aliases_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("aliases_only", new SecuredString("test123".toCharArray()))))
|
||||
.admin().indices().prepareCreate("test_1").get();
|
||||
fail("Expected ElasticsearchSecurityException");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
assertThat(e.getMessage(), is("action [indices:admin/create] is unauthorized for user [aliases_only]"));
|
||||
|
@ -605,25 +566,24 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
|
|||
}
|
||||
|
||||
public void testGetAliasesAliasesOnlyPermission() {
|
||||
Map<String, String> headers = Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue("aliases_only", new SecuredString("test123".toCharArray())));
|
||||
final Client client = client().filterWithHeader(headers);
|
||||
//user has manage_aliases only permissions on both alias_* and test_*
|
||||
|
||||
//ok: manage_aliases on both test_* and alias_*
|
||||
GetAliasesResponse getAliasesResponse = client().admin().indices().prepareGetAliases("alias_1").addIndices("test_1").setIndicesOptions(IndicesOptions.lenientExpandOpen())
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("aliases_only", new SecuredString("test123".toCharArray()))).get();
|
||||
GetAliasesResponse getAliasesResponse = client.admin().indices().prepareGetAliases("alias_1").addIndices("test_1").setIndicesOptions(IndicesOptions.lenientExpandOpen()).get();
|
||||
assertThat(getAliasesResponse.getAliases().isEmpty(), is(true));
|
||||
|
||||
try {
|
||||
//fails: no manage_aliases privilege on non_authorized alias
|
||||
client().admin().indices().prepareGetAliases("non_authorized").addIndices("test_1").setIndicesOptions(IndicesOptions.lenientExpandOpen())
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("aliases_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareGetAliases("non_authorized").addIndices("test_1").setIndicesOptions(IndicesOptions.lenientExpandOpen()).get();
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases/get] is unauthorized for user [aliases_only]"));
|
||||
}
|
||||
|
||||
try {
|
||||
//fails: no manage_aliases privilege on non_authorized index
|
||||
client().admin().indices().prepareGetAliases("alias_1").addIndices("non_authorized").setIndicesOptions(IndicesOptions.lenientExpandOpen())
|
||||
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("aliases_only", new SecuredString("test123".toCharArray()))).get();
|
||||
client.admin().indices().prepareGetAliases("alias_1").addIndices("non_authorized").setIndicesOptions(IndicesOptions.lenientExpandOpen()).get();
|
||||
} catch(ElasticsearchSecurityException e) {
|
||||
assertAuthorizationException(e, containsString("action [indices:admin/aliases/get] is unauthorized for user [aliases_only]"));
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.elasticsearch.cluster.metadata.AliasMetaData;
|
|||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.search.action.SearchServiceTransportAction;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.audit.AuditTrail;
|
||||
|
@ -34,6 +35,7 @@ import org.elasticsearch.shield.authz.privilege.GeneralPrivilege;
|
|||
import org.elasticsearch.shield.authz.privilege.IndexPrivilege;
|
||||
import org.elasticsearch.shield.authz.store.RolesStore;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.junit.Before;
|
||||
|
||||
|
@ -56,6 +58,8 @@ public class InternalAuthorizationServiceTests extends ESTestCase {
|
|||
private RolesStore rolesStore;
|
||||
private ClusterService clusterService;
|
||||
private InternalAuthorizationService internalAuthorizationService;
|
||||
private ThreadContext threadContext;
|
||||
private ThreadPool threadPool;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
|
@ -63,7 +67,12 @@ public class InternalAuthorizationServiceTests extends ESTestCase {
|
|||
clusterService = mock(ClusterService.class);
|
||||
auditTrail = mock(AuditTrail.class);
|
||||
AnonymousService anonymousService = new AnonymousService(Settings.EMPTY);
|
||||
internalAuthorizationService = new InternalAuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail, anonymousService, new DefaultAuthenticationFailureHandler());
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
threadPool = mock(ThreadPool.class);
|
||||
when(threadPool.getThreadContext()).thenReturn(threadContext);
|
||||
|
||||
internalAuthorizationService = new InternalAuthorizationService(Settings.EMPTY, rolesStore, clusterService,
|
||||
auditTrail, anonymousService, new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
}
|
||||
|
||||
public void testActionsSystemUserIsAuthorized() {
|
||||
|
@ -297,7 +306,7 @@ public class InternalAuthorizationServiceTests extends ESTestCase {
|
|||
TransportRequest request = new IndicesExistsRequest("b");
|
||||
ClusterState state = mock(ClusterState.class);
|
||||
AnonymousService anonymousService = new AnonymousService(Settings.builder().put("shield.authc.anonymous.roles", "a_all").build());
|
||||
internalAuthorizationService = new InternalAuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail, anonymousService, new DefaultAuthenticationFailureHandler());
|
||||
internalAuthorizationService = new InternalAuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail, anonymousService, new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
|
||||
when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build());
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
|
@ -322,7 +331,7 @@ public class InternalAuthorizationServiceTests extends ESTestCase {
|
|||
.put("shield.authc.anonymous.roles", "a_all")
|
||||
.put(AnonymousService.SETTING_AUTHORIZATION_EXCEPTION_ENABLED, false)
|
||||
.build());
|
||||
internalAuthorizationService = new InternalAuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail, anonymousService, new DefaultAuthenticationFailureHandler());
|
||||
internalAuthorizationService = new InternalAuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail, anonymousService, new DefaultAuthenticationFailureHandler(), threadPool);
|
||||
|
||||
when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build());
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.elasticsearch.common.bytes.BytesArray;
|
|||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.lucene.index.ElasticsearchDirectoryReader;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.IndexSettings;
|
||||
import org.elasticsearch.index.cache.bitset.BitsetFilterCache;
|
||||
|
@ -36,7 +37,6 @@ import org.elasticsearch.shield.authz.InternalAuthorizationService;
|
|||
import org.elasticsearch.shield.license.ShieldLicenseState;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.IndexSettingsModule;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
|
@ -65,10 +65,8 @@ public class ShieldIndexSearcherWrapperIntegrationTests extends ESTestCase {
|
|||
}
|
||||
});
|
||||
|
||||
TransportRequest request = new TransportRequest.Empty();
|
||||
RequestContext.setCurrent(new RequestContext(request));
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
IndicesAccessControl.IndexAccessControl indexAccessControl = new IndicesAccessControl.IndexAccessControl(true, null, singleton(new BytesArray("{}")));
|
||||
request.putInContext(InternalAuthorizationService.INDICES_PERMISSIONS_KEY, new IndicesAccessControl(true, singletonMap("_index", indexAccessControl)));
|
||||
IndexSettings indexSettings = IndexSettingsModule.newIndexSettings(shardId.index(), Settings.EMPTY);
|
||||
QueryShardContext queryShardContext = mock(QueryShardContext.class);
|
||||
IndexSettings settings = IndexSettingsModule.newIndexSettings(new Index("_index"), Settings.EMPTY);
|
||||
|
@ -85,12 +83,17 @@ public class ShieldIndexSearcherWrapperIntegrationTests extends ESTestCase {
|
|||
});
|
||||
ShieldLicenseState licenseState = mock(ShieldLicenseState.class);
|
||||
when(licenseState.documentAndFieldLevelSecurityEnabled()).thenReturn(true);
|
||||
ShieldIndexSearcherWrapper wrapper = new ShieldIndexSearcherWrapper(indexSettings, queryShardContext, mapperService, bitsetFilterCache, licenseState) {
|
||||
ShieldIndexSearcherWrapper wrapper = new ShieldIndexSearcherWrapper(indexSettings, queryShardContext, mapperService, bitsetFilterCache, threadContext, licenseState) {
|
||||
|
||||
@Override
|
||||
protected QueryShardContext copyQueryShardContext(QueryShardContext context) {
|
||||
return queryShardContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IndicesAccessControl getIndicesAccessControl() {
|
||||
return new IndicesAccessControl(true, singletonMap("_index", indexAccessControl));
|
||||
}
|
||||
};
|
||||
|
||||
Directory directory = newDirectory();
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.apache.lucene.util.SparseFixedBitSet;
|
|||
import org.elasticsearch.common.compress.CompressedXContent;
|
||||
import org.elasticsearch.common.lucene.index.ElasticsearchDirectoryReader;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.IndexSettings;
|
||||
|
@ -43,11 +44,9 @@ import org.elasticsearch.index.similarity.SimilarityService;
|
|||
import org.elasticsearch.indices.IndicesModule;
|
||||
import org.elasticsearch.indices.IndicesWarmer;
|
||||
import org.elasticsearch.search.aggregations.LeafBucketCollector;
|
||||
import org.elasticsearch.shield.authz.InternalAuthorizationService;
|
||||
import org.elasticsearch.shield.license.ShieldLicenseState;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.IndexSettingsModule;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
|
@ -68,16 +67,17 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
public class ShieldIndexSearcherWrapperUnitTests extends ESTestCase {
|
||||
|
||||
private TransportRequest request;
|
||||
private ThreadContext threadContext;
|
||||
private MapperService mapperService;
|
||||
private ShieldIndexSearcherWrapper shieldIndexSearcherWrapper;
|
||||
private ElasticsearchDirectoryReader esIn;
|
||||
private ShieldLicenseState licenseState;
|
||||
private IndexSettings indexSettings;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
Index index = new Index("_index");
|
||||
IndexSettings indexSettings = IndexSettingsModule.newIndexSettings(index, Settings.EMPTY);
|
||||
indexSettings = IndexSettingsModule.newIndexSettings(index, Settings.EMPTY);
|
||||
AnalysisService analysisService = new AnalysisService(indexSettings, Collections.emptyMap(), Collections.emptyMap(),
|
||||
Collections.emptyMap(), Collections.emptyMap());
|
||||
SimilarityService similarityService = new SimilarityService(indexSettings, Collections.emptyMap());
|
||||
|
@ -86,13 +86,10 @@ public class ShieldIndexSearcherWrapperUnitTests extends ESTestCase {
|
|||
ShardId shardId = new ShardId(index, 0);
|
||||
licenseState = mock(ShieldLicenseState.class);
|
||||
when(licenseState.documentAndFieldLevelSecurityEnabled()).thenReturn(true);
|
||||
shieldIndexSearcherWrapper = new ShieldIndexSearcherWrapper(indexSettings, null, mapperService, null, licenseState);
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
IndexShard indexShard = mock(IndexShard.class);
|
||||
when(indexShard.shardId()).thenReturn(shardId);
|
||||
|
||||
request = new TransportRequest.Empty();
|
||||
RequestContext.setCurrent(new RequestContext(request));
|
||||
|
||||
Directory directory = new RAMDirectory();
|
||||
IndexWriter writer = new IndexWriter(directory, newIndexWriterConfig());
|
||||
writer.close();
|
||||
|
@ -106,16 +103,6 @@ public class ShieldIndexSearcherWrapperUnitTests extends ESTestCase {
|
|||
esIn.close();
|
||||
}
|
||||
|
||||
public void testUnkownOriginOfCurrentCall() {
|
||||
RequestContext.setCurrent(null);
|
||||
try {
|
||||
shieldIndexSearcherWrapper.wrap(esIn);
|
||||
fail("exception expected");
|
||||
} catch (IllegalStateException e) {
|
||||
assertThat(e.getMessage(), equalTo("can't locate the origin of the current request"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testDefaultMetaFields() throws Exception {
|
||||
XContentBuilder mappingSource = jsonBuilder().startObject().startObject("type")
|
||||
.startObject("properties")
|
||||
|
@ -123,8 +110,13 @@ public class ShieldIndexSearcherWrapperUnitTests extends ESTestCase {
|
|||
.endObject().endObject();
|
||||
mapperService.merge("type", new CompressedXContent(mappingSource.string()), MapperService.MergeReason.MAPPING_UPDATE, false);
|
||||
|
||||
IndicesAccessControl.IndexAccessControl indexAccessControl = new IndicesAccessControl.IndexAccessControl(true, emptySet(), null);
|
||||
request.putInContext(InternalAuthorizationService.INDICES_PERMISSIONS_KEY, new IndicesAccessControl(true, singletonMap("_index", indexAccessControl)));
|
||||
shieldIndexSearcherWrapper = new ShieldIndexSearcherWrapper(indexSettings, null, mapperService, null, threadContext, licenseState) {
|
||||
@Override
|
||||
protected IndicesAccessControl getIndicesAccessControl() {
|
||||
IndicesAccessControl.IndexAccessControl indexAccessControl = new IndicesAccessControl.IndexAccessControl(true, emptySet(), null);
|
||||
return new IndicesAccessControl(true, singletonMap("_index", indexAccessControl));
|
||||
}
|
||||
};
|
||||
|
||||
FieldSubsetReader.FieldSubsetDirectoryReader result = (FieldSubsetReader.FieldSubsetDirectoryReader) shieldIndexSearcherWrapper.wrap(esIn);
|
||||
assertThat(result.getFieldNames().size(), equalTo(11));
|
||||
|
@ -144,12 +136,14 @@ public class ShieldIndexSearcherWrapperUnitTests extends ESTestCase {
|
|||
|
||||
public void testWrapReaderWhenFeatureDisabled() throws Exception {
|
||||
when(licenseState.documentAndFieldLevelSecurityEnabled()).thenReturn(false);
|
||||
shieldIndexSearcherWrapper = new ShieldIndexSearcherWrapper(indexSettings, null, mapperService, null, threadContext, licenseState);
|
||||
DirectoryReader reader = shieldIndexSearcherWrapper.wrap(esIn);
|
||||
assertThat(reader, sameInstance(esIn));
|
||||
}
|
||||
|
||||
public void testWrapSearcherWhenFeatureDisabled() throws Exception {
|
||||
ShardId shardId = new ShardId("_index", 0);
|
||||
shieldIndexSearcherWrapper = new ShieldIndexSearcherWrapper(indexSettings, null, mapperService, null, threadContext, licenseState);
|
||||
IndexSearcher indexSearcher = new IndexSearcher(esIn);
|
||||
IndexSearcher result = shieldIndexSearcherWrapper.wrap(indexSearcher);
|
||||
assertThat(result, sameInstance(indexSearcher));
|
||||
|
@ -262,6 +256,7 @@ public class ShieldIndexSearcherWrapperUnitTests extends ESTestCase {
|
|||
});
|
||||
DirectoryReader directoryReader = DocumentSubsetReader.wrap(esIn, bitsetFilterCache, new MatchAllDocsQuery());
|
||||
IndexSearcher indexSearcher = new IndexSearcher(directoryReader);
|
||||
shieldIndexSearcherWrapper = new ShieldIndexSearcherWrapper(indexSettings, null, mapperService, null, threadContext, licenseState);
|
||||
IndexSearcher result = shieldIndexSearcherWrapper.wrap(indexSearcher);
|
||||
assertThat(result, not(sameInstance(indexSearcher)));
|
||||
assertThat(result.getSimilarity(true), sameInstance(indexSearcher.getSimilarity(true)));
|
||||
|
@ -269,6 +264,7 @@ public class ShieldIndexSearcherWrapperUnitTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testIntersectScorerAndRoleBits() throws Exception {
|
||||
shieldIndexSearcherWrapper = new ShieldIndexSearcherWrapper(indexSettings, null, mapperService, null, threadContext, licenseState);
|
||||
final Directory directory = newDirectory();
|
||||
IndexWriter iw = new IndexWriter(
|
||||
directory,
|
||||
|
@ -356,8 +352,13 @@ public class ShieldIndexSearcherWrapperUnitTests extends ESTestCase {
|
|||
}
|
||||
|
||||
private void assertResolvedFields(String expression, String... expectedFields) {
|
||||
IndicesAccessControl.IndexAccessControl indexAccessControl = new IndicesAccessControl.IndexAccessControl(true, singleton(expression), null);
|
||||
request.putInContext(InternalAuthorizationService.INDICES_PERMISSIONS_KEY, new IndicesAccessControl(true, singletonMap("_index", indexAccessControl)));
|
||||
shieldIndexSearcherWrapper = new ShieldIndexSearcherWrapper(indexSettings, null, mapperService, null, threadContext, licenseState) {
|
||||
@Override
|
||||
protected IndicesAccessControl getIndicesAccessControl() {
|
||||
IndicesAccessControl.IndexAccessControl indexAccessControl = new IndicesAccessControl.IndexAccessControl(true, singleton(expression), null);
|
||||
return new IndicesAccessControl(true, singletonMap("_index", indexAccessControl));
|
||||
}
|
||||
};
|
||||
FieldSubsetReader.FieldSubsetDirectoryReader result = (FieldSubsetReader.FieldSubsetDirectoryReader) shieldIndexSearcherWrapper.wrap(esIn);
|
||||
assertThat(result.getFieldNames().size() - shieldIndexSearcherWrapper.getAllowedMetaFields().size(), equalTo(expectedFields.length));
|
||||
for (String expectedField : expectedFields) {
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.shield.rest;
|
|||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestFilterChain;
|
||||
|
@ -15,6 +16,7 @@ import org.elasticsearch.shield.User;
|
|||
import org.elasticsearch.shield.authc.AuthenticationService;
|
||||
import org.elasticsearch.shield.license.ShieldLicenseState;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.junit.Before;
|
||||
|
||||
import static org.elasticsearch.shield.support.Exceptions.authenticationError;
|
||||
|
@ -42,7 +44,9 @@ public class ShieldRestFilterTests extends ESTestCase {
|
|||
chain = mock(RestFilterChain.class);
|
||||
licenseState = mock(ShieldLicenseState.class);
|
||||
when(licenseState.securityEnabled()).thenReturn(true);
|
||||
filter = new ShieldRestFilter(authcService, restController, Settings.EMPTY, licenseState);
|
||||
ThreadPool threadPool = mock(ThreadPool.class);
|
||||
when(threadPool.getThreadContext()).thenReturn(new ThreadContext(Settings.EMPTY));
|
||||
filter = new ShieldRestFilter(authcService, restController, Settings.EMPTY, threadPool, licenseState);
|
||||
verify(restController).registerFilter(filter);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,6 @@ public class ClientTransportFilterTests extends ESTestCase {
|
|||
public void testOutbound() throws Exception {
|
||||
TransportRequest request = mock(TransportRequest.class);
|
||||
filter.outbound("_action", request);
|
||||
verify(authcService).attachUserHeaderIfMissing(request, User.SYSTEM);
|
||||
verify(authcService).attachUserHeaderIfMissing(User.SYSTEM);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
package org.elasticsearch.shield.transport;
|
||||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.User;
|
||||
import org.elasticsearch.shield.action.ShieldActionMapper;
|
||||
import org.elasticsearch.shield.authc.AuthenticationService;
|
||||
|
@ -40,7 +42,7 @@ public class ServerTransportFilterTests extends ESTestCase {
|
|||
authzService = mock(AuthorizationService.class);
|
||||
channel = mock(NettyTransportChannel.class);
|
||||
when(channel.getProfileName()).thenReturn(NettyTransport.DEFAULT_PROFILE);
|
||||
filter = new ServerTransportFilter.NodeProfile(authcService, authzService, new ShieldActionMapper(), false);
|
||||
filter = new ServerTransportFilter.NodeProfile(authcService, authzService, new ShieldActionMapper(), new ThreadContext(Settings.EMPTY), false);
|
||||
}
|
||||
|
||||
public void testInbound() throws Exception {
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.shield.ssl.ServerSSLService;
|
|||
import org.elasticsearch.shield.transport.SSLClientAuth;
|
||||
import org.elasticsearch.shield.transport.filter.IPFilter;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.ssl.SslHandler;
|
||||
import org.junit.Before;
|
||||
|
@ -45,7 +46,7 @@ public class ShieldNettyHttpServerTransportTests extends ESTestCase {
|
|||
|
||||
public void testDefaultClientAuth() throws Exception {
|
||||
Settings settings = Settings.builder().put(ShieldNettyHttpServerTransport.HTTP_SSL_SETTING, true).build();
|
||||
ShieldNettyHttpServerTransport transport = new ShieldNettyHttpServerTransport(settings, mock(NetworkService.class), mock(BigArrays.class), mock(IPFilter.class), serverSSLService);
|
||||
ShieldNettyHttpServerTransport transport = new ShieldNettyHttpServerTransport(settings, mock(NetworkService.class), mock(BigArrays.class), mock(IPFilter.class), serverSSLService, mock(ThreadPool.class));
|
||||
NettyHttpMockUtil.setOpenChannelsHandlerToMock(transport);
|
||||
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory();
|
||||
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(false));
|
||||
|
@ -57,7 +58,7 @@ public class ShieldNettyHttpServerTransportTests extends ESTestCase {
|
|||
Settings settings = Settings.builder()
|
||||
.put(ShieldNettyHttpServerTransport.HTTP_SSL_SETTING, true)
|
||||
.put(ShieldNettyHttpServerTransport.HTTP_CLIENT_AUTH_SETTING, value).build();
|
||||
ShieldNettyHttpServerTransport transport = new ShieldNettyHttpServerTransport(settings, mock(NetworkService.class), mock(BigArrays.class), mock(IPFilter.class), serverSSLService);
|
||||
ShieldNettyHttpServerTransport transport = new ShieldNettyHttpServerTransport(settings, mock(NetworkService.class), mock(BigArrays.class), mock(IPFilter.class), serverSSLService, mock(ThreadPool.class));
|
||||
NettyHttpMockUtil.setOpenChannelsHandlerToMock(transport);
|
||||
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory();
|
||||
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(false));
|
||||
|
@ -69,7 +70,7 @@ public class ShieldNettyHttpServerTransportTests extends ESTestCase {
|
|||
Settings settings = Settings.builder()
|
||||
.put(ShieldNettyHttpServerTransport.HTTP_SSL_SETTING, true)
|
||||
.put(ShieldNettyHttpServerTransport.HTTP_CLIENT_AUTH_SETTING, value).build();
|
||||
ShieldNettyHttpServerTransport transport = new ShieldNettyHttpServerTransport(settings, mock(NetworkService.class), mock(BigArrays.class), mock(IPFilter.class), serverSSLService);
|
||||
ShieldNettyHttpServerTransport transport = new ShieldNettyHttpServerTransport(settings, mock(NetworkService.class), mock(BigArrays.class), mock(IPFilter.class), serverSSLService, mock(ThreadPool.class));
|
||||
NettyHttpMockUtil.setOpenChannelsHandlerToMock(transport);
|
||||
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory();
|
||||
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(true));
|
||||
|
@ -81,7 +82,7 @@ public class ShieldNettyHttpServerTransportTests extends ESTestCase {
|
|||
Settings settings = Settings.builder()
|
||||
.put(ShieldNettyHttpServerTransport.HTTP_SSL_SETTING, true)
|
||||
.put(ShieldNettyHttpServerTransport.HTTP_CLIENT_AUTH_SETTING, value).build();
|
||||
ShieldNettyHttpServerTransport transport = new ShieldNettyHttpServerTransport(settings, mock(NetworkService.class), mock(BigArrays.class), mock(IPFilter.class), serverSSLService);
|
||||
ShieldNettyHttpServerTransport transport = new ShieldNettyHttpServerTransport(settings, mock(NetworkService.class), mock(BigArrays.class), mock(IPFilter.class), serverSSLService, mock(ThreadPool.class));
|
||||
NettyHttpMockUtil.setOpenChannelsHandlerToMock(transport);
|
||||
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory();
|
||||
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(false));
|
||||
|
|
|
@ -9,8 +9,8 @@ import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
|||
import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
|
||||
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.cluster.health.ClusterHealthStatus;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
|
@ -26,10 +26,14 @@ import org.junit.rules.ExternalResource;
|
|||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
|
||||
|
@ -303,4 +307,17 @@ public abstract class ShieldIntegTestCase extends ESIntegTestCase {
|
|||
assertNoTimeout(clusterHealthResponse);
|
||||
assertThat(clusterHealthResponse.getStatus(), is(ClusterHealthStatus.GREEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<Client,Client> getClientWrapper() {
|
||||
Map<String, String> headers = Collections.singletonMap("Authorization", basicAuthHeaderValue(nodeClientUsername(), nodeClientPassword()));
|
||||
// we need to wrap node clients because we do not specify a shield user for nodes and all requests will use the system
|
||||
// user. This is ok for internal n2n stuff but the test framework does other things like wiping indices, repositories, etc
|
||||
// that the system user cannot do. so we wrap the node client with a user that can do these things since the client() calls
|
||||
// are randomized to return both node clients and transport clients
|
||||
// transport clients do not need to be wrapped since we specify the shield.user setting that sets the default user to be
|
||||
// used for the transport client. If we did not set a default user then the transport client would not even be allowed
|
||||
// to connect
|
||||
return client -> (client instanceof NodeClient) ? client.filterWithHeader(headers) : client;
|
||||
}
|
||||
}
|
|
@ -6,9 +6,9 @@
|
|||
package org.elasticsearch.test;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.client.support.Headers;
|
||||
import org.elasticsearch.common.io.PathUtils;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.index.IndexModule;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.shield.ShieldPlugin;
|
||||
|
@ -16,7 +16,6 @@ import org.elasticsearch.shield.authc.esusers.ESUsersRealm;
|
|||
import org.elasticsearch.shield.authc.esnative.ESNativeRealm;
|
||||
import org.elasticsearch.shield.authc.support.Hasher;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.shield.crypto.InternalCryptoService;
|
||||
import org.elasticsearch.shield.test.ShieldTestUtils;
|
||||
import org.elasticsearch.shield.transport.netty.ShieldNettyHttpServerTransport;
|
||||
|
@ -134,13 +133,11 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ
|
|||
.put("shield.authc.realms.index.type", ESNativeRealm.TYPE)
|
||||
.put("shield.authc.realms.index.order", "1")
|
||||
.put("shield.authz.store.files.roles", writeFile(folder, "roles.yml", configRoles()))
|
||||
// Test framework sometimes randomily selects the 'index' or 'none' cache and that makes the
|
||||
// Test framework sometimes randomly selects the 'index' or 'none' cache and that makes the
|
||||
// validation in ShieldPlugin fail.
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING.getKey(), ShieldPlugin.OPT_OUT_QUERY_CACHE)
|
||||
.put(getNodeSSLSettings());
|
||||
|
||||
setUser(builder, nodeClientUsername(), nodeClientPassword());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
@ -148,7 +145,11 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ
|
|||
public Settings transportClientSettings() {
|
||||
Settings.Builder builder = settingsBuilder().put(super.transportClientSettings())
|
||||
.put(getClientSSLSettings());
|
||||
setUser(builder, transportClientUsername(), transportClientPassword());
|
||||
if (randomBoolean()) {
|
||||
builder.put("shield.user", transportClientUsername() + ":" + new String(transportClientPassword().internalChars()));
|
||||
} else {
|
||||
builder.put(ThreadContext.PREFIX + ".Authorization", basicAuthHeaderValue(transportClientUsername(), transportClientPassword()));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
@ -198,14 +199,6 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ
|
|||
return XPackPlugin.class;
|
||||
}
|
||||
|
||||
private void setUser(Settings.Builder builder, String username, SecuredString password) {
|
||||
if (randomBoolean()) {
|
||||
builder.put(Headers.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER, basicAuthHeaderValue(username, password));
|
||||
} else {
|
||||
builder.put("shield.user", username + ":" + new String(password.internalChars()));
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] generateKey() {
|
||||
try {
|
||||
return InternalCryptoService.generateKey();
|
||||
|
|
|
@ -15,8 +15,8 @@ import org.apache.http.client.methods.HttpPut;
|
|||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
||||
import org.elasticsearch.client.support.Headers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
|
@ -67,7 +67,7 @@ public abstract class XPackRestTestCase extends ESRestTestCase {
|
|||
protected Settings restClientSettings() {
|
||||
String token = basicAuthHeaderValue("test_user", new SecuredString("changeme".toCharArray()));
|
||||
return Settings.builder()
|
||||
.put(Headers.PREFIX + ".Authorization", token)
|
||||
.put(ThreadContext.PREFIX + ".Authorization", token)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.elasticsearch.watcher.client;
|
|||
import org.elasticsearch.action.ActionFuture;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.watcher.transport.actions.ack.AckWatchAction;
|
||||
import org.elasticsearch.watcher.transport.actions.ack.AckWatchRequest;
|
||||
|
@ -43,11 +42,13 @@ import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsRequest;
|
|||
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsRequestBuilder;
|
||||
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsResponse;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class WatcherClient {
|
||||
|
||||
private final ElasticsearchClient client;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
public WatcherClient(Client client) {
|
||||
|
@ -323,4 +324,7 @@ public class WatcherClient {
|
|||
return client.execute(ExecuteWatchAction.INSTANCE, request);
|
||||
}
|
||||
|
||||
public WatcherClient filterWithHeader(Map<String, String> headers) {
|
||||
return new WatcherClient(client.filterWithHeader(headers));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,8 @@ public class ExecutionService extends AbstractComponent {
|
|||
}
|
||||
|
||||
public List<QueuedWatch> queuedWatches() {
|
||||
List<Runnable> snapshot = new ArrayList<>(executor.queue());
|
||||
List<Runnable> snapshot = new ArrayList<>();
|
||||
executor.tasks().forEach(t -> snapshot.add(t));
|
||||
if (snapshot.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue