mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-09 14:34:43 +00:00
test: Add more Shield related tests for testing the Watcher roles.
Original commit: elastic/x-pack-elasticsearch@482d8fe65c
This commit is contained in:
parent
284a60e16d
commit
2861f8ce21
@ -35,6 +35,7 @@ import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||
import org.elasticsearch.test.InternalTestCluster;
|
||||
import org.elasticsearch.test.TestCluster;
|
||||
import org.elasticsearch.watcher.WatcherLifeCycleService;
|
||||
import org.elasticsearch.watcher.WatcherPlugin;
|
||||
import org.elasticsearch.watcher.WatcherService;
|
||||
import org.elasticsearch.watcher.WatcherState;
|
||||
@ -155,7 +156,7 @@ public abstract class AbstractWatcherIntegrationTests extends ElasticsearchInteg
|
||||
if (checkWatcherRunningOnlyOnce()) {
|
||||
ensureWatcherOnlyRunningOnce();
|
||||
}
|
||||
stopWatcher();
|
||||
stopWatcher(false);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@ -189,15 +190,15 @@ public abstract class AbstractWatcherIntegrationTests extends ElasticsearchInteg
|
||||
private void startWatcherIfNodesExist() throws Exception {
|
||||
if (internalTestCluster().size() > 0) {
|
||||
ensureLicenseEnabled();
|
||||
WatcherStatsResponse response = watcherClient().prepareWatcherStats().get();
|
||||
if (response.getWatcherState() == WatcherState.STOPPED) {
|
||||
WatcherState state = getInstanceFromMaster(WatcherService.class).state();
|
||||
if (state == WatcherState.STOPPED) {
|
||||
logger.info("[{}#{}]: starting watcher", getTestClass().getSimpleName(), getTestName());
|
||||
startWatcher();
|
||||
} else if (response.getWatcherState() == WatcherState.STARTING) {
|
||||
startWatcher(false);
|
||||
} else if (state == WatcherState.STARTING) {
|
||||
logger.info("[{}#{}]: watcher is starting, waiting for it to get in a started state", getTestClass().getSimpleName(), getTestName());
|
||||
ensureWatcherStarted(false);
|
||||
} else {
|
||||
logger.info("[{}#{}]: not starting watcher, because watcher is in state [{}]", getTestClass().getSimpleName(), getTestName(), response.getWatcherState());
|
||||
logger.info("[{}#{}]: not starting watcher, because watcher is in state [{}]", getTestClass().getSimpleName(), getTestName(), state);
|
||||
}
|
||||
} else {
|
||||
logger.info("[{}#{}]: not starting watcher, because test cluster has no nodes", getTestClass().getSimpleName(), getTestName());
|
||||
@ -427,13 +428,29 @@ public abstract class AbstractWatcherIntegrationTests extends ElasticsearchInteg
|
||||
}
|
||||
|
||||
protected void startWatcher() throws Exception {
|
||||
watcherClient().prepareWatchService().start().get();
|
||||
ensureWatcherStarted(false);
|
||||
startWatcher(true);
|
||||
}
|
||||
|
||||
protected void stopWatcher() throws Exception {
|
||||
stopWatcher(true);
|
||||
}
|
||||
|
||||
protected void startWatcher(boolean useClient) throws Exception {
|
||||
if (useClient) {
|
||||
watcherClient().prepareWatchService().start().get();
|
||||
} else {
|
||||
getInstanceFromMaster(WatcherLifeCycleService.class).start();
|
||||
}
|
||||
ensureWatcherStarted(useClient);
|
||||
}
|
||||
|
||||
protected void stopWatcher(boolean useClient) throws Exception {
|
||||
if (useClient) {
|
||||
watcherClient().prepareWatchService().stop().get();
|
||||
ensureWatcherStopped(false);
|
||||
} else {
|
||||
getInstanceFromMaster(WatcherLifeCycleService.class).stop();
|
||||
}
|
||||
ensureWatcherStopped(useClient);
|
||||
}
|
||||
|
||||
protected void ensureWatcherOnlyRunningOnce() {
|
||||
@ -587,8 +604,6 @@ public abstract class AbstractWatcherIntegrationTests extends ElasticsearchInteg
|
||||
|
||||
public static final String TEST_USERNAME = "test";
|
||||
public static final String TEST_PASSWORD = "changeme";
|
||||
public static final String TEST_BASIC_AUTH_TOKEN = UsernamePasswordToken.basicAuthHeaderValue(TEST_USERNAME, new SecuredString(TEST_PASSWORD.toCharArray()));
|
||||
public static final String ADMIN_BASIC_AUTH_TOKEN = UsernamePasswordToken.basicAuthHeaderValue("admin", new SecuredString("changeme".toCharArray()));
|
||||
|
||||
static boolean auditLogsEnabled = SystemPropertyUtil.getBoolean("tests.audit_logs", true);
|
||||
static byte[] systemKey = generateKey(); // must be the same for all nodes
|
||||
@ -596,23 +611,27 @@ public abstract class AbstractWatcherIntegrationTests extends ElasticsearchInteg
|
||||
public static final String IP_FILTER = "allow: all\n";
|
||||
|
||||
public static final String USERS =
|
||||
"transport_client:{plain}changeme\n" +
|
||||
TEST_USERNAME + ":{plain}" + TEST_PASSWORD + "\n" +
|
||||
"admin:{plain}changeme\n" +
|
||||
"monitor:{plain}changeme";
|
||||
|
||||
public static final String USER_ROLES =
|
||||
"transport_client:transport_client\n" +
|
||||
"test:test\n" +
|
||||
"admin:admin\n" +
|
||||
"monitor:monitor";
|
||||
|
||||
public static final String ROLES =
|
||||
"test:\n" + // a user for the test infra.
|
||||
" cluster: all\n" +
|
||||
" cluster: cluster:monitor/state, cluster:monitor/health, indices:admin/template/delete, cluster:admin/repository/delete, indices:admin/template/put, cluster:monitor/stats\n" +
|
||||
" indices:\n" +
|
||||
" '*': all\n" +
|
||||
"\n" +
|
||||
"admin:\n" +
|
||||
" cluster: manage_watcher, cluster:monitor/nodes/info\n" +
|
||||
"transport_client:\n" +
|
||||
" cluster: cluster:monitor/nodes/info\n" +
|
||||
"\n" +
|
||||
"monitor:\n" +
|
||||
" cluster: monitor_watcher, cluster:monitor/nodes/info\n"
|
||||
|
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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.watcher.test.integration;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.joda.time.DateTime;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.shield.ShieldPlugin;
|
||||
import org.elasticsearch.shield.authc.AuthenticationException;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authz.AuthorizationException;
|
||||
import org.elasticsearch.watcher.WatcherPlugin;
|
||||
import org.elasticsearch.watcher.WatcherState;
|
||||
import org.elasticsearch.watcher.client.WatchSourceBuilders;
|
||||
import org.elasticsearch.watcher.condition.ConditionBuilders;
|
||||
import org.elasticsearch.watcher.test.AbstractWatcherIntegrationTests;
|
||||
import org.elasticsearch.watcher.transport.actions.delete.DeleteWatchResponse;
|
||||
import org.elasticsearch.watcher.transport.actions.execute.ExecuteWatchResponse;
|
||||
import org.elasticsearch.watcher.transport.actions.get.GetWatchResponse;
|
||||
import org.elasticsearch.watcher.transport.actions.put.PutWatchResponse;
|
||||
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsResponse;
|
||||
import org.elasticsearch.watcher.trigger.TriggerBuilders;
|
||||
import org.elasticsearch.watcher.trigger.TriggerEvent;
|
||||
import org.elasticsearch.watcher.trigger.schedule.IntervalSchedule;
|
||||
import org.elasticsearch.watcher.trigger.schedule.ScheduleTriggerEvent;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.elasticsearch.common.joda.time.DateTimeZone.UTC;
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.watcher.client.WatchSourceBuilders.watchBuilder;
|
||||
import static org.elasticsearch.watcher.trigger.TriggerBuilders.schedule;
|
||||
import static org.elasticsearch.watcher.trigger.schedule.Schedules.interval;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
|
||||
public class BasicShieldTests extends AbstractWatcherIntegrationTests {
|
||||
|
||||
@Override
|
||||
protected boolean enableShield() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Settings transportClientSettings() {
|
||||
return ImmutableSettings.builder()
|
||||
.put("client.transport.sniff", false)
|
||||
.put("plugin.types", ShieldPlugin.class.getName() + "," + WatcherPlugin.class.getName())
|
||||
// Use just the transport user here, so we can test Watcher roles specifically
|
||||
.put("shield.user", "transport_client:changeme")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoAuthorization() throws Exception {
|
||||
try {
|
||||
watcherClient().prepareWatcherStats().get();
|
||||
fail("authentication failure should have occurred");
|
||||
} catch (AuthorizationException e) {
|
||||
// transport_client is the default user
|
||||
assertThat(e.getMessage(), equalTo("action [cluster:monitor/watcher/stats] is unauthorized for user [transport_client]"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWatcherMonitorRole() throws Exception {
|
||||
// stats and get watch apis require at least monitor role:
|
||||
String token = basicAuthHeaderValue("test", new SecuredString("changeme".toCharArray()));
|
||||
try {
|
||||
watcherClient().prepareWatcherStats()
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
fail("authentication failure should have occurred");
|
||||
} catch (AuthorizationException e) {
|
||||
assertThat(e.getMessage(), equalTo("action [cluster:monitor/watcher/stats] is unauthorized for user [test]"));
|
||||
}
|
||||
|
||||
try {
|
||||
watcherClient().prepareGetWatch("_id")
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
fail("authentication failure should have occurred");
|
||||
} catch (AuthorizationException e) {
|
||||
assertThat(e.getMessage(), equalTo("action [cluster:monitor/watcher/watch/get] is unauthorized for user [test]"));
|
||||
}
|
||||
|
||||
// stats and get watch are allowed by role monitor:
|
||||
token = basicAuthHeaderValue("monitor", new SecuredString("changeme".toCharArray()));
|
||||
WatcherStatsResponse statsResponse = watcherClient().prepareWatcherStats()
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
assertThat(statsResponse.getWatcherState(), equalTo(WatcherState.STARTED));
|
||||
GetWatchResponse getWatchResponse = watcherClient().prepareGetWatch("_id")
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
assertThat(getWatchResponse.isFound(), is(false));
|
||||
|
||||
// but put watch isn't allowed by monitor:
|
||||
try {
|
||||
watcherClient().preparePutWatch("_id")
|
||||
.setSource(watchBuilder().trigger(schedule(interval(5, IntervalSchedule.Interval.Unit.SECONDS))))
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
fail("authentication failure should have occurred");
|
||||
} catch (AuthorizationException e) {
|
||||
assertThat(e.getMessage(), equalTo("action [cluster:admin/watcher/watch/put] is unauthorized for user [monitor]"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWatcherAdminRole() throws Exception {
|
||||
// put, execute and delete watch apis requires watcher admin role:
|
||||
String token = basicAuthHeaderValue("test", new SecuredString("changeme".toCharArray()));
|
||||
try {
|
||||
watcherClient().preparePutWatch("_id")
|
||||
.setSource(watchBuilder().trigger(schedule(interval(5, IntervalSchedule.Interval.Unit.SECONDS))))
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
fail("authentication failure should have occurred");
|
||||
} catch (AuthorizationException e) {
|
||||
assertThat(e.getMessage(), equalTo("action [cluster:admin/watcher/watch/put] is unauthorized for user [test]"));
|
||||
}
|
||||
|
||||
TriggerEvent triggerEvent = new ScheduleTriggerEvent(new DateTime(UTC), new DateTime(UTC));
|
||||
try {
|
||||
watcherClient().prepareExecuteWatch("_id")
|
||||
.setTriggerEvent(triggerEvent)
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
fail("authentication failure should have occurred");
|
||||
} catch (AuthorizationException e) {
|
||||
assertThat(e.getMessage(), equalTo("action [cluster:admin/watcher/watch/execute] is unauthorized for user [test]"));
|
||||
}
|
||||
|
||||
try {
|
||||
watcherClient().prepareDeleteWatch("_id")
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
fail("authentication failure should have occurred");
|
||||
} catch (AuthorizationException e) {
|
||||
assertThat(e.getMessage(), equalTo("action [cluster:admin/watcher/watch/delete] is unauthorized for user [test]"));
|
||||
}
|
||||
|
||||
// put, execute and delete watch apis are allowed by role admin:
|
||||
token = basicAuthHeaderValue("admin", new SecuredString("changeme".toCharArray()));
|
||||
PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id")
|
||||
.setSource(watchBuilder().trigger(schedule(interval(5, IntervalSchedule.Interval.Unit.SECONDS))))
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
assertThat(putWatchResponse.getVersion(), equalTo(1l));
|
||||
ExecuteWatchResponse executeWatchResponse = watcherClient().prepareExecuteWatch("_id")
|
||||
.setTriggerEvent(triggerEvent)
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
DeleteWatchResponse deleteWatchResponse = watcherClient().prepareDeleteWatch("_id")
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
assertThat(deleteWatchResponse.getVersion(), equalTo(2l));
|
||||
assertThat(deleteWatchResponse.isFound(), is(true));
|
||||
|
||||
// stats and get watch are also allowed by role monitor:
|
||||
token = basicAuthHeaderValue("monitor", new SecuredString("changeme".toCharArray()));
|
||||
WatcherStatsResponse statsResponse = watcherClient().prepareWatcherStats()
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
assertThat(statsResponse.getWatcherState(), equalTo(WatcherState.STARTED));
|
||||
GetWatchResponse getWatchResponse = watcherClient().prepareGetWatch("_id")
|
||||
.putHeader("Authorization", token)
|
||||
.get();
|
||||
assertThat(getWatchResponse.isFound(), is(false));
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user