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.ElasticsearchIntegrationTest.ClusterScope;
|
||||||
import org.elasticsearch.test.InternalTestCluster;
|
import org.elasticsearch.test.InternalTestCluster;
|
||||||
import org.elasticsearch.test.TestCluster;
|
import org.elasticsearch.test.TestCluster;
|
||||||
|
import org.elasticsearch.watcher.WatcherLifeCycleService;
|
||||||
import org.elasticsearch.watcher.WatcherPlugin;
|
import org.elasticsearch.watcher.WatcherPlugin;
|
||||||
import org.elasticsearch.watcher.WatcherService;
|
import org.elasticsearch.watcher.WatcherService;
|
||||||
import org.elasticsearch.watcher.WatcherState;
|
import org.elasticsearch.watcher.WatcherState;
|
||||||
@ -155,7 +156,7 @@ public abstract class AbstractWatcherIntegrationTests extends ElasticsearchInteg
|
|||||||
if (checkWatcherRunningOnlyOnce()) {
|
if (checkWatcherRunningOnlyOnce()) {
|
||||||
ensureWatcherOnlyRunningOnce();
|
ensureWatcherOnlyRunningOnce();
|
||||||
}
|
}
|
||||||
stopWatcher();
|
stopWatcher(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
@ -189,15 +190,15 @@ public abstract class AbstractWatcherIntegrationTests extends ElasticsearchInteg
|
|||||||
private void startWatcherIfNodesExist() throws Exception {
|
private void startWatcherIfNodesExist() throws Exception {
|
||||||
if (internalTestCluster().size() > 0) {
|
if (internalTestCluster().size() > 0) {
|
||||||
ensureLicenseEnabled();
|
ensureLicenseEnabled();
|
||||||
WatcherStatsResponse response = watcherClient().prepareWatcherStats().get();
|
WatcherState state = getInstanceFromMaster(WatcherService.class).state();
|
||||||
if (response.getWatcherState() == WatcherState.STOPPED) {
|
if (state == WatcherState.STOPPED) {
|
||||||
logger.info("[{}#{}]: starting watcher", getTestClass().getSimpleName(), getTestName());
|
logger.info("[{}#{}]: starting watcher", getTestClass().getSimpleName(), getTestName());
|
||||||
startWatcher();
|
startWatcher(false);
|
||||||
} else if (response.getWatcherState() == WatcherState.STARTING) {
|
} else if (state == WatcherState.STARTING) {
|
||||||
logger.info("[{}#{}]: watcher is starting, waiting for it to get in a started state", getTestClass().getSimpleName(), getTestName());
|
logger.info("[{}#{}]: watcher is starting, waiting for it to get in a started state", getTestClass().getSimpleName(), getTestName());
|
||||||
ensureWatcherStarted(false);
|
ensureWatcherStarted(false);
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
logger.info("[{}#{}]: not starting watcher, because test cluster has no nodes", getTestClass().getSimpleName(), getTestName());
|
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 {
|
protected void startWatcher() throws Exception {
|
||||||
watcherClient().prepareWatchService().start().get();
|
startWatcher(true);
|
||||||
ensureWatcherStarted(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void stopWatcher() throws Exception {
|
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();
|
watcherClient().prepareWatchService().stop().get();
|
||||||
ensureWatcherStopped(false);
|
} else {
|
||||||
|
getInstanceFromMaster(WatcherLifeCycleService.class).stop();
|
||||||
|
}
|
||||||
|
ensureWatcherStopped(useClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void ensureWatcherOnlyRunningOnce() {
|
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_USERNAME = "test";
|
||||||
public static final String TEST_PASSWORD = "changeme";
|
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 boolean auditLogsEnabled = SystemPropertyUtil.getBoolean("tests.audit_logs", true);
|
||||||
static byte[] systemKey = generateKey(); // must be the same for all nodes
|
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 IP_FILTER = "allow: all\n";
|
||||||
|
|
||||||
public static final String USERS =
|
public static final String USERS =
|
||||||
|
"transport_client:{plain}changeme\n" +
|
||||||
TEST_USERNAME + ":{plain}" + TEST_PASSWORD + "\n" +
|
TEST_USERNAME + ":{plain}" + TEST_PASSWORD + "\n" +
|
||||||
"admin:{plain}changeme\n" +
|
"admin:{plain}changeme\n" +
|
||||||
"monitor:{plain}changeme";
|
"monitor:{plain}changeme";
|
||||||
|
|
||||||
public static final String USER_ROLES =
|
public static final String USER_ROLES =
|
||||||
|
"transport_client:transport_client\n" +
|
||||||
"test:test\n" +
|
"test:test\n" +
|
||||||
"admin:admin\n" +
|
"admin:admin\n" +
|
||||||
"monitor:monitor";
|
"monitor:monitor";
|
||||||
|
|
||||||
public static final String ROLES =
|
public static final String ROLES =
|
||||||
"test:\n" + // a user for the test infra.
|
"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" +
|
" indices:\n" +
|
||||||
" '*': all\n" +
|
" '*': all\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"admin:\n" +
|
"admin:\n" +
|
||||||
" cluster: manage_watcher, cluster:monitor/nodes/info\n" +
|
" cluster: manage_watcher, cluster:monitor/nodes/info\n" +
|
||||||
|
"transport_client:\n" +
|
||||||
|
" cluster: cluster:monitor/nodes/info\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"monitor:\n" +
|
"monitor:\n" +
|
||||||
" cluster: monitor_watcher, cluster:monitor/nodes/info\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