mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-06 04:58:50 +00:00
Merge branch 'master' into feature/async_rest_client
Original commit: elastic/x-pack-elasticsearch@693e281d0d
This commit is contained in:
commit
ca557af48c
@ -101,6 +101,7 @@ public class License implements ToXContent {
|
||||
case "gold":
|
||||
return GOLD;
|
||||
case "platinum":
|
||||
case "cloud_internal":
|
||||
case "internal": // bwc for 1.x subscription_type field
|
||||
return PLATINUM;
|
||||
default:
|
||||
@ -196,12 +197,42 @@ public class License implements ToXContent {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the operation mode of the license as computed from the license type
|
||||
* @return the operation mode of the license as computed from the license type or from
|
||||
* the license mode file
|
||||
*/
|
||||
public OperationMode operationMode() {
|
||||
synchronized (this) {
|
||||
if (canReadOperationModeFromFile() && operationModeFileWatcher != null) {
|
||||
return operationModeFileWatcher.getCurrentOperationMode();
|
||||
}
|
||||
}
|
||||
return operationMode;
|
||||
}
|
||||
|
||||
private boolean canReadOperationModeFromFile() {
|
||||
return type.equals("cloud_internal");
|
||||
}
|
||||
|
||||
private volatile OperationModeFileWatcher operationModeFileWatcher;
|
||||
|
||||
/**
|
||||
* Sets the operation mode file watcher for the license and initializes the
|
||||
* file watcher when the license type allows to override operation mode from file
|
||||
*/
|
||||
public synchronized void setOperationModeFileWatcher(final OperationModeFileWatcher operationModeFileWatcher) {
|
||||
this.operationModeFileWatcher = operationModeFileWatcher;
|
||||
if (canReadOperationModeFromFile()) {
|
||||
this.operationModeFileWatcher.init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes operation mode file watcher, so unused license objects can be gc'ed
|
||||
*/
|
||||
public synchronized void removeOperationModeFileWatcher() {
|
||||
this.operationModeFileWatcher = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current license's status
|
||||
*/
|
||||
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.license.core;
|
||||
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.license.core.License.OperationMode;
|
||||
import org.elasticsearch.watcher.FileChangesListener;
|
||||
import org.elasticsearch.watcher.FileWatcher;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* File based watcher for license {@link OperationMode}
|
||||
* Watches for changes in <code>licenseModePath</code>, use
|
||||
* {@link #getCurrentOperationMode()} to access the latest mode
|
||||
*
|
||||
* In case of failure to read a valid operation mode from <code>licenseModePath</code>,
|
||||
* the operation mode will default to PLATINUM
|
||||
*/
|
||||
public final class OperationModeFileWatcher extends FileChangesListener {
|
||||
private final ResourceWatcherService resourceWatcherService;
|
||||
private final Path licenseModePath;
|
||||
private final AtomicBoolean initialized = new AtomicBoolean();
|
||||
private final OperationMode defaultOperationMode = OperationMode.PLATINUM;
|
||||
private volatile OperationMode currentOperationMode = defaultOperationMode;
|
||||
private final ESLogger logger;
|
||||
private final Runnable onChange;
|
||||
|
||||
public OperationModeFileWatcher(ResourceWatcherService resourceWatcherService, Path licenseModePath,
|
||||
ESLogger logger, Runnable onChange) {
|
||||
this.resourceWatcherService = resourceWatcherService;
|
||||
this.licenseModePath = licenseModePath;
|
||||
this.logger = logger;
|
||||
this.onChange = onChange;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
if (initialized.compareAndSet(false, true)) {
|
||||
final FileWatcher watcher = new FileWatcher(licenseModePath);
|
||||
watcher.addListener(this);
|
||||
try {
|
||||
resourceWatcherService.add(watcher, ResourceWatcherService.Frequency.HIGH);
|
||||
if (Files.exists(licenseModePath)) {
|
||||
onChange(licenseModePath);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("couldn't initialize watching license mode file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current operation mode based on license mode file.
|
||||
* Defaults to {@link OperationMode#PLATINUM}
|
||||
*/
|
||||
public OperationMode getCurrentOperationMode() {
|
||||
return currentOperationMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileInit(Path file) {
|
||||
onChange(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileCreated(Path file) {
|
||||
onChange(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileDeleted(Path file) {
|
||||
onChange(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileChanged(Path file) {
|
||||
onChange(file);
|
||||
}
|
||||
|
||||
private synchronized void onChange(Path file) {
|
||||
if (file.equals(licenseModePath)) {
|
||||
currentOperationMode = defaultOperationMode;
|
||||
if (Files.exists(licenseModePath)
|
||||
&& Files.isReadable(licenseModePath)) {
|
||||
final byte[] content;
|
||||
try {
|
||||
content = Files.readAllBytes(licenseModePath);
|
||||
} catch (IOException e) {
|
||||
logger.error("couldn't read operation mode from [{}]", e, licenseModePath.toAbsolutePath().toString());
|
||||
return;
|
||||
}
|
||||
String operationMode = new String(content, StandardCharsets.UTF_8);
|
||||
try {
|
||||
currentOperationMode = OperationMode.resolve(operationMode);
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.error("invalid operation mode in [{}]", e, licenseModePath.toAbsolutePath().toString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
onChange.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.license.core;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.watcher.FileWatcher;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.elasticsearch.license.core.OperationModeFileWatcherTests.writeMode;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
public class LicenseOperationModeUpdateTests extends ESTestCase {
|
||||
|
||||
private OperationModeFileWatcher operationModeFileWatcher;
|
||||
private Path licenseModeFile;
|
||||
private ResourceWatcherService resourceWatcherService;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
licenseModeFile = createTempFile();
|
||||
resourceWatcherService = mock(ResourceWatcherService.class);
|
||||
operationModeFileWatcher = new OperationModeFileWatcher(resourceWatcherService, licenseModeFile, logger, () -> {});
|
||||
}
|
||||
|
||||
public void testLicenseOperationModeUpdate() throws Exception {
|
||||
String type = randomFrom("trial", "basic", "standard", "gold", "platinum");
|
||||
License license = License.builder()
|
||||
.uid("id")
|
||||
.expiryDate(0)
|
||||
.issueDate(0)
|
||||
.issuedTo("elasticsearch")
|
||||
.issuer("issuer")
|
||||
.type(type)
|
||||
.maxNodes(1)
|
||||
.build();
|
||||
|
||||
assertThat(license.operationMode(), equalTo(License.OperationMode.resolve(type)));
|
||||
writeMode("gold", licenseModeFile);
|
||||
license.setOperationModeFileWatcher(operationModeFileWatcher);
|
||||
verifyZeroInteractions(resourceWatcherService);
|
||||
assertThat(license.operationMode(), equalTo(License.OperationMode.resolve(type)));
|
||||
}
|
||||
|
||||
public void testCloudInternalLicenseOperationModeUpdate() throws Exception {
|
||||
License license = License.builder()
|
||||
.uid("id")
|
||||
.expiryDate(0)
|
||||
.issueDate(0)
|
||||
.issuedTo("elasticsearch")
|
||||
.issuer("issuer")
|
||||
.type("cloud_internal")
|
||||
.maxNodes(1)
|
||||
.build();
|
||||
|
||||
assertThat(license.operationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
writeMode("gold", licenseModeFile);
|
||||
license.setOperationModeFileWatcher(operationModeFileWatcher);
|
||||
verify(resourceWatcherService, times(1)).add(any(FileWatcher.class), eq(ResourceWatcherService.Frequency.HIGH));
|
||||
assertThat(license.operationMode(), equalTo(License.OperationMode.GOLD));
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.license.core;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.TestThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class OperationModeFileWatcherTests extends ESTestCase {
|
||||
private ResourceWatcherService watcherService;
|
||||
private TestThreadPool threadPool;
|
||||
private Path licenseModePath;
|
||||
private OperationModeFileWatcher operationModeFileWatcher;
|
||||
private AtomicInteger onChangeCounter;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
threadPool = new TestThreadPool("license mode file watcher tests");
|
||||
Settings settings = Settings.builder()
|
||||
.put("resource.reload.interval.high", "10ms")
|
||||
.build();
|
||||
watcherService = new ResourceWatcherService(settings,
|
||||
threadPool);
|
||||
watcherService.start();
|
||||
licenseModePath = createTempFile();
|
||||
onChangeCounter = new AtomicInteger();
|
||||
operationModeFileWatcher = new OperationModeFileWatcher(watcherService, licenseModePath, logger,
|
||||
() -> onChangeCounter.incrementAndGet());
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown() throws InterruptedException {
|
||||
terminate(threadPool);
|
||||
watcherService.stop();
|
||||
}
|
||||
|
||||
public void testInit() throws Exception {
|
||||
writeMode("gold");
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
operationModeFileWatcher.init();
|
||||
assertThat(onChangeCounter.get(), equalTo(2));
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.GOLD));
|
||||
}
|
||||
|
||||
public void testUpdateModeFromFile() throws Exception {
|
||||
Files.delete(licenseModePath);
|
||||
operationModeFileWatcher.init();
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
writeMode("gold");
|
||||
assertBusy(() -> assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.GOLD)));
|
||||
writeMode("basic");
|
||||
assertBusy(() -> assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.BASIC)));
|
||||
assertThat(onChangeCounter.get(), equalTo(2));
|
||||
}
|
||||
|
||||
public void testDeleteModeFromFile() throws Exception {
|
||||
Files.delete(licenseModePath);
|
||||
operationModeFileWatcher.init();
|
||||
writeMode("gold");
|
||||
assertBusy(() -> assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.GOLD)));
|
||||
Files.delete(licenseModePath);
|
||||
assertBusy(() -> assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM)));
|
||||
assertThat(onChangeCounter.get(), equalTo(2));
|
||||
}
|
||||
|
||||
public void testInvalidModeFromFile() throws Exception {
|
||||
writeMode("invalid");
|
||||
operationModeFileWatcher.init();
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
operationModeFileWatcher.onFileChanged(licenseModePath);
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
}
|
||||
|
||||
public void testLicenseModeFileIsDirectory() throws Exception {
|
||||
licenseModePath = createTempDir();
|
||||
operationModeFileWatcher.init();
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
operationModeFileWatcher.onFileChanged(licenseModePath);
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
}
|
||||
|
||||
public void testLicenseModeFileCreatedAfterInit() throws Exception {
|
||||
Files.delete(licenseModePath);
|
||||
operationModeFileWatcher.init();
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
Path tempFile = createTempFile();
|
||||
writeMode("gold", tempFile);
|
||||
licenseModePath = tempFile;
|
||||
assertBusy(() -> assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.GOLD)));
|
||||
}
|
||||
|
||||
private void writeMode(String mode) throws IOException {
|
||||
writeMode(mode, licenseModePath);
|
||||
}
|
||||
|
||||
static void writeMode(String mode, Path file) throws IOException {
|
||||
Files.write(file, mode.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ project.sourceSets.test.output.dir(outputDir, builtBy: copyXPackPluginProps)
|
||||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.security.audit.enabled', 'true'
|
||||
setting 'xpack.security.audit.outputs', 'index'
|
||||
setting 'logger.level', 'DEBUG'
|
||||
|
@ -34,7 +34,7 @@ integTest {
|
||||
'search/80_date_math_index_names/Missing index with catch'].join(',')
|
||||
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.watcher.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
setupCommand 'setupDummyUser',
|
||||
|
@ -14,7 +14,7 @@ import org.elasticsearch.xpack.watcher.condition.script.ScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.execution.ManualExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.execution.ManualExecutionTests.ExecutionRunner;
|
||||
import org.elasticsearch.xpack.watcher.history.WatchRecord;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.transport.actions.delete.DeleteWatchResponse;
|
||||
import org.elasticsearch.xpack.watcher.transport.actions.get.GetWatchRequest;
|
||||
@ -65,7 +65,7 @@ public class GroovyManualExecutionIT extends AbstractWatcherIntegrationTestCase
|
||||
WatchSourceBuilder watchBuilder = watchBuilder()
|
||||
.trigger(schedule(cron("0 0 0 1 * ? 2099")))
|
||||
.input(simpleInput("foo", "bar"))
|
||||
.condition(new ScriptCondition((new Script.Builder.Inline("sleep 100; return true")).build()))
|
||||
.condition(new ScriptCondition((new WatcherScript.Builder.Inline("sleep 100; return true")).build()))
|
||||
.addAction("log", loggingAction("foobar"));
|
||||
|
||||
Watch watch = watchParser().parse("_id", false, watchBuilder.buildAsBytes(XContentType.JSON));
|
||||
@ -80,7 +80,7 @@ public class GroovyManualExecutionIT extends AbstractWatcherIntegrationTestCase
|
||||
WatchSourceBuilder watchBuilder = watchBuilder()
|
||||
.trigger(schedule(cron("0 0 0 1 * ? 2099")))
|
||||
.input(simpleInput("foo", "bar"))
|
||||
.condition(new ScriptCondition((new Script.Builder.Inline("sleep 10000; return true")).build()))
|
||||
.condition(new ScriptCondition((new WatcherScript.Builder.Inline("sleep 10000; return true")).build()))
|
||||
.defaultThrottlePeriod(new TimeValue(1, TimeUnit.HOURS))
|
||||
.addAction("log", loggingAction("foobar"));
|
||||
|
||||
|
@ -8,6 +8,7 @@ package org.elasticsearch.messy.tests;
|
||||
import org.elasticsearch.action.search.SearchRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.groovy.GroovyPlugin;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
|
||||
@ -16,8 +17,7 @@ import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ExecutableScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.watch.Payload;
|
||||
import org.junit.AfterClass;
|
||||
@ -28,7 +28,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.elasticsearch.messy.tests.MessyTestUtils.getScriptServiceProxy;
|
||||
import static org.elasticsearch.messy.tests.MessyTestUtils.createScriptService;
|
||||
import static org.elasticsearch.xpack.watcher.test.WatcherTestUtils.mockExecutionContext;
|
||||
|
||||
public class GroovyScriptConditionIT extends AbstractWatcherIntegrationTestCase {
|
||||
@ -46,7 +46,7 @@ public class GroovyScriptConditionIT extends AbstractWatcherIntegrationTestCase
|
||||
}
|
||||
|
||||
private static ThreadPool THREAD_POOL;
|
||||
private ScriptServiceProxy scriptService;
|
||||
private ScriptService scriptService;
|
||||
|
||||
@BeforeClass
|
||||
public static void startThreadPool() {
|
||||
@ -55,7 +55,7 @@ public class GroovyScriptConditionIT extends AbstractWatcherIntegrationTestCase
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
scriptService = getScriptServiceProxy(THREAD_POOL);
|
||||
scriptService = createScriptService(THREAD_POOL);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@ -83,7 +83,7 @@ public class GroovyScriptConditionIT extends AbstractWatcherIntegrationTestCase
|
||||
SearchResponse unmetResponse = builder.get();
|
||||
|
||||
ExecutableScriptCondition condition =
|
||||
new ExecutableScriptCondition(new ScriptCondition(Script.inline(
|
||||
new ExecutableScriptCondition(new ScriptCondition(WatcherScript.inline(
|
||||
String.join(
|
||||
" ",
|
||||
"if (ctx.payload.hits.total < 1) return false;",
|
||||
|
@ -6,9 +6,6 @@
|
||||
package org.elasticsearch.messy.tests;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.SuppressForbidden;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
@ -19,9 +16,8 @@ import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.script.groovy.GroovyScriptEngineService;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.junit.Ignore;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@ -29,7 +25,7 @@ import java.util.Collections;
|
||||
@Ignore // not a test.
|
||||
@SuppressForbidden(reason = "gradle is broken and tries to run me as a test")
|
||||
public final class MessyTestUtils {
|
||||
public static ScriptServiceProxy getScriptServiceProxy(ThreadPool tp) throws Exception {
|
||||
public static ScriptService createScriptService(ThreadPool tp) throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put("script.inline", "true")
|
||||
.put("script.indexed", "true")
|
||||
@ -37,10 +33,10 @@ public final class MessyTestUtils {
|
||||
.build();
|
||||
GroovyScriptEngineService groovyScriptEngineService = new GroovyScriptEngineService(settings);
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singleton(groovyScriptEngineService));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Arrays.asList(ScriptServiceProxy.INSTANCE));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Arrays.asList(WatcherScript.CTX_PLUGIN));
|
||||
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
return ScriptServiceProxy.of(new ScriptService(settings, new Environment(settings),
|
||||
new ResourceWatcherService(settings, tp), scriptEngineRegistry, scriptContextRegistry, scriptSettings));
|
||||
return new ScriptService(settings, new Environment(settings), new ResourceWatcherService(settings, tp),
|
||||
scriptEngineRegistry, scriptContextRegistry, scriptSettings);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import org.elasticsearch.action.search.ShardSearchFailure;
|
||||
import org.elasticsearch.common.text.Text;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.groovy.GroovyPlugin;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||
@ -20,11 +21,10 @@ import org.elasticsearch.search.internal.InternalSearchHits;
|
||||
import org.elasticsearch.search.internal.InternalSearchResponse;
|
||||
import org.elasticsearch.threadpool.TestThreadPool;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ExecutableScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.watch.Payload;
|
||||
import org.junit.After;
|
||||
@ -40,7 +40,7 @@ import static org.mockito.Mockito.when;
|
||||
*/
|
||||
public class ScriptConditionSearchIT extends AbstractWatcherIntegrationTestCase {
|
||||
private ThreadPool tp = null;
|
||||
private ScriptServiceProxy scriptService;
|
||||
private ScriptService scriptService;
|
||||
|
||||
@Override
|
||||
protected List<Class<? extends Plugin>> pluginTypes() {
|
||||
@ -52,7 +52,7 @@ public class ScriptConditionSearchIT extends AbstractWatcherIntegrationTestCase
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
tp = new TestThreadPool(ThreadPool.Names.SAME);
|
||||
scriptService = MessyTestUtils.getScriptServiceProxy(tp);
|
||||
scriptService = MessyTestUtils.createScriptService(tp);
|
||||
}
|
||||
|
||||
@After
|
||||
@ -73,7 +73,7 @@ public class ScriptConditionSearchIT extends AbstractWatcherIntegrationTestCase
|
||||
.get();
|
||||
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(
|
||||
new ScriptCondition(Script.inline("ctx.payload.aggregations.rate.buckets[0]?.doc_count >= 5").build()),
|
||||
new ScriptCondition(WatcherScript.inline("ctx.payload.aggregations.rate.buckets[0]?.doc_count >= 5").build()),
|
||||
logger, scriptService);
|
||||
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
@ -92,7 +92,7 @@ public class ScriptConditionSearchIT extends AbstractWatcherIntegrationTestCase
|
||||
|
||||
public void testExecuteAccessHits() throws Exception {
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(new ScriptCondition(
|
||||
Script.inline("ctx.payload.hits?.hits[0]?._score == 1.0").build()), logger, scriptService);
|
||||
WatcherScript.inline("ctx.payload.hits?.hits[0]?._score == 1.0").build()), logger, scriptService);
|
||||
InternalSearchHit hit = new InternalSearchHit(0, "1", new Text("type"), null);
|
||||
hit.score(1f);
|
||||
hit.shard(new SearchShardTarget("a", new Index("a", "testUUID"), 0));
|
||||
|
@ -15,17 +15,17 @@ import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.GeneralScriptException;
|
||||
import org.elasticsearch.script.ScriptException;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
import org.elasticsearch.search.internal.InternalSearchResponse;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.TestThreadPool;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ExecutableScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ScriptConditionFactory;
|
||||
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.watch.Payload;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
@ -36,7 +36,7 @@ import java.io.IOException;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.messy.tests.MessyTestUtils.getScriptServiceProxy;
|
||||
import static org.elasticsearch.messy.tests.MessyTestUtils.createScriptService;
|
||||
import static org.elasticsearch.xpack.watcher.support.Exceptions.illegalArgument;
|
||||
import static org.elasticsearch.xpack.watcher.test.WatcherTestUtils.mockExecutionContext;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
@ -57,18 +57,18 @@ public class ScriptConditionTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testExecute() throws Exception {
|
||||
ScriptServiceProxy scriptService = getScriptServiceProxy(tp);
|
||||
ScriptService scriptService = createScriptService(tp);
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(
|
||||
new ScriptCondition(Script.inline("ctx.payload.hits.total > 1").build()), logger, scriptService);
|
||||
new ScriptCondition(WatcherScript.inline("ctx.payload.hits.total > 1").build()), logger, scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500L, new ShardSearchFailure[0]);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
assertFalse(condition.execute(ctx).met());
|
||||
}
|
||||
|
||||
public void testExecuteMergedParams() throws Exception {
|
||||
ScriptServiceProxy scriptService = getScriptServiceProxy(tp);
|
||||
Script script = Script.inline("ctx.payload.hits.total > threshold")
|
||||
.lang(Script.DEFAULT_LANG).params(singletonMap("threshold", 1)).build();
|
||||
ScriptService scriptService = createScriptService(tp);
|
||||
WatcherScript script = WatcherScript.inline("ctx.payload.hits.total > threshold")
|
||||
.lang(WatcherScript.DEFAULT_LANG).params(singletonMap("threshold", 1)).build();
|
||||
ExecutableScriptCondition executable = new ExecutableScriptCondition(new ScriptCondition(script), logger, scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500L, new ShardSearchFailure[0]);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
@ -76,7 +76,7 @@ public class ScriptConditionTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testParserValid() throws Exception {
|
||||
ScriptConditionFactory factory = new ScriptConditionFactory(Settings.builder().build(), getScriptServiceProxy(tp));
|
||||
ScriptConditionFactory factory = new ScriptConditionFactory(Settings.builder().build(), createScriptService(tp));
|
||||
|
||||
XContentBuilder builder = createConditionContent("ctx.payload.hits.total > 1", null, ScriptType.INLINE);
|
||||
|
||||
@ -103,7 +103,7 @@ public class ScriptConditionTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testParserInvalid() throws Exception {
|
||||
ScriptConditionFactory factory = new ScriptConditionFactory(Settings.builder().build(), getScriptServiceProxy(tp));
|
||||
ScriptConditionFactory factory = new ScriptConditionFactory(Settings.builder().build(), createScriptService(tp));
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
builder.startObject().endObject();
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
@ -118,7 +118,7 @@ public class ScriptConditionTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testScriptConditionParserBadScript() throws Exception {
|
||||
ScriptConditionFactory conditionParser = new ScriptConditionFactory(Settings.builder().build(), getScriptServiceProxy(tp));
|
||||
ScriptConditionFactory conditionParser = new ScriptConditionFactory(Settings.builder().build(), createScriptService(tp));
|
||||
ScriptType scriptType = randomFrom(ScriptType.values());
|
||||
String script;
|
||||
switch (scriptType) {
|
||||
@ -139,7 +139,7 @@ public class ScriptConditionTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testScriptConditionParser_badLang() throws Exception {
|
||||
ScriptConditionFactory conditionParser = new ScriptConditionFactory(Settings.builder().build(), getScriptServiceProxy(tp));
|
||||
ScriptConditionFactory conditionParser = new ScriptConditionFactory(Settings.builder().build(), createScriptService(tp));
|
||||
ScriptType scriptType = ScriptType.INLINE;
|
||||
String script = "return true";
|
||||
XContentBuilder builder = createConditionContent(script, "not_a_valid_lang", scriptType);
|
||||
@ -152,9 +152,9 @@ public class ScriptConditionTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testScriptConditionThrowException() throws Exception {
|
||||
ScriptServiceProxy scriptService = getScriptServiceProxy(tp);
|
||||
ScriptService scriptService = createScriptService(tp);
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(
|
||||
new ScriptCondition(Script.inline("null.foo").build()), logger, scriptService);
|
||||
new ScriptCondition(WatcherScript.inline("null.foo").build()), logger, scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500L, new ShardSearchFailure[0]);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
ScriptException exception = expectThrows(ScriptException.class, () -> condition.execute(ctx));
|
||||
@ -162,9 +162,9 @@ public class ScriptConditionTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testScriptConditionReturnObjectThrowsException() throws Exception {
|
||||
ScriptServiceProxy scriptService = getScriptServiceProxy(tp);
|
||||
ScriptService scriptService = createScriptService(tp);
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(
|
||||
new ScriptCondition(Script.inline("return new Object()").build()), logger, scriptService);
|
||||
new ScriptCondition(WatcherScript.inline("return new Object()").build()), logger, scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500L, new ShardSearchFailure[0]);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
Exception exception = expectThrows(GeneralScriptException.class, () -> condition.execute(ctx));
|
||||
@ -173,9 +173,9 @@ public class ScriptConditionTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testScriptConditionAccessCtx() throws Exception {
|
||||
ScriptServiceProxy scriptService = getScriptServiceProxy(tp);
|
||||
ScriptService scriptService = createScriptService(tp);
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(
|
||||
new ScriptCondition(Script.inline("ctx.trigger.scheduled_time.getMillis() < new Date().time ").build()),
|
||||
new ScriptCondition(WatcherScript.inline("ctx.trigger.scheduled_time.getMillis() < new Date().time ").build()),
|
||||
logger, scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500L, new ShardSearchFailure[0]);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new DateTime(DateTimeZone.UTC), new Payload.XContent(response));
|
||||
|
@ -13,7 +13,7 @@ import org.elasticsearch.common.io.Streams;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.groovy.GroovyPlugin;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.test.WatcherTestUtils;
|
||||
import org.elasticsearch.xpack.watcher.transport.actions.put.PutWatchResponse;
|
||||
@ -72,10 +72,10 @@ public class TransformIT extends AbstractWatcherIntegrationTestCase {
|
||||
}
|
||||
|
||||
public void testScriptTransform() throws Exception {
|
||||
final Script script;
|
||||
final WatcherScript script;
|
||||
if (randomBoolean()) {
|
||||
logger.info("testing script transform with an inline script");
|
||||
script = Script.inline("return [key3 : ctx.payload.key1 + ctx.payload.key2]").lang("groovy").build();
|
||||
script = WatcherScript.inline("return [key3 : ctx.payload.key1 + ctx.payload.key2]").lang("groovy").build();
|
||||
} else if (randomBoolean()) {
|
||||
logger.info("testing script transform with an indexed script");
|
||||
client().admin().cluster().preparePutStoredScript()
|
||||
@ -83,10 +83,10 @@ public class TransformIT extends AbstractWatcherIntegrationTestCase {
|
||||
.setScriptLang("groovy")
|
||||
.setSource(new BytesArray("{\"script\" : \"return [key3 : ctx.payload.key1 + ctx.payload.key2]\"}"))
|
||||
.get();
|
||||
script = Script.indexed("_id").lang("groovy").build();
|
||||
script = WatcherScript.indexed("_id").lang("groovy").build();
|
||||
} else {
|
||||
logger.info("testing script transform with a file script");
|
||||
script = Script.file("my-script").lang("groovy").build();
|
||||
script = WatcherScript.file("my-script").lang("groovy").build();
|
||||
}
|
||||
|
||||
// put a watch that has watch level transform:
|
||||
@ -182,8 +182,8 @@ public class TransformIT extends AbstractWatcherIntegrationTestCase {
|
||||
}
|
||||
|
||||
public void testChainTransform() throws Exception {
|
||||
final Script script1 = Script.inline("return [key3 : ctx.payload.key1 + ctx.payload.key2]").lang("groovy").build();
|
||||
final Script script2 = Script.inline("return [key4 : ctx.payload.key3 + 10]").lang("groovy").build();
|
||||
final WatcherScript script1 = WatcherScript.inline("return [key3 : ctx.payload.key1 + ctx.payload.key2]").lang("groovy").build();
|
||||
final WatcherScript script2 = WatcherScript.inline("return [key4 : ctx.payload.key3 + 10]").lang("groovy").build();
|
||||
// put a watch that has watch level transform:
|
||||
PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id1")
|
||||
.setSource(watchBuilder()
|
||||
|
@ -28,7 +28,6 @@ import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.search.suggest.Suggesters;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.common.text.TextTemplate;
|
||||
import org.elasticsearch.xpack.watcher.actions.ActionWrapper;
|
||||
import org.elasticsearch.xpack.watcher.actions.ExecutableActions;
|
||||
@ -41,7 +40,7 @@ import org.elasticsearch.xpack.watcher.input.search.SearchInput;
|
||||
import org.elasticsearch.xpack.watcher.input.search.SearchInputFactory;
|
||||
import org.elasticsearch.xpack.watcher.input.simple.ExecutableSimpleInput;
|
||||
import org.elasticsearch.xpack.watcher.input.simple.SimpleInput;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.support.init.proxy.WatcherClientProxy;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateRequest;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService;
|
||||
@ -190,7 +189,7 @@ public class SearchInputIT extends ESIntegTestCase {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.inline(TEMPLATE_QUERY).lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.inline(TEMPLATE_QUERY).lang("mustache").params(params).build();
|
||||
|
||||
SearchRequest request = client().prepareSearch()
|
||||
.setSearchType(ExecutableSearchInput.DEFAULT_SEARCH_TYPE)
|
||||
@ -224,7 +223,7 @@ public class SearchInputIT extends ESIntegTestCase {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.indexed("test-template").lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.indexed("test-template").lang("mustache").params(params).build();
|
||||
|
||||
jsonBuilder().value(TextTemplate.indexed("test-template").params(params).build()).bytes();
|
||||
SearchRequest request = client().prepareSearch().setSearchType(ExecutableSearchInput.DEFAULT_SEARCH_TYPE)
|
||||
@ -252,7 +251,7 @@ public class SearchInputIT extends ESIntegTestCase {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.file("test_disk_template").lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.file("test_disk_template").lang("mustache").params(params).build();
|
||||
SearchRequest request = client().prepareSearch().setSearchType(ExecutableSearchInput.DEFAULT_SEARCH_TYPE)
|
||||
.setIndices("test-search-index").request();
|
||||
|
||||
@ -347,7 +346,8 @@ public class SearchInputIT extends ESIntegTestCase {
|
||||
timeValueSeconds(5));
|
||||
}
|
||||
|
||||
private SearchInput.Result executeSearchInput(SearchRequest request, Script template, WatchExecutionContext ctx) throws IOException {
|
||||
private SearchInput.Result executeSearchInput(SearchRequest request, WatcherScript template,
|
||||
WatchExecutionContext ctx) throws IOException {
|
||||
createIndex("test-search-index");
|
||||
ensureGreen("test-search-index");
|
||||
SearchInput.Builder siBuilder = SearchInput.builder(new WatcherSearchTemplateRequest(request, template));
|
||||
@ -362,15 +362,15 @@ public class SearchInputIT extends ESIntegTestCase {
|
||||
protected WatcherSearchTemplateService watcherSearchTemplateService() {
|
||||
String master = internalCluster().getMasterName();
|
||||
return new WatcherSearchTemplateService(internalCluster().clusterService(master).getSettings(),
|
||||
ScriptServiceProxy.of(internalCluster().getInstance(ScriptService.class, master)),
|
||||
internalCluster().getInstance(ScriptService.class, master),
|
||||
internalCluster().getInstance(IndicesQueriesRegistry.class, master),
|
||||
internalCluster().getInstance(AggregatorParsers.class, master),
|
||||
internalCluster().getInstance(Suggesters.class, master)
|
||||
);
|
||||
}
|
||||
|
||||
protected ScriptServiceProxy scriptService() {
|
||||
return ScriptServiceProxy.of(internalCluster().getInstance(ScriptService.class));
|
||||
protected ScriptService scriptService() {
|
||||
return internalCluster().getInstance(ScriptService.class);
|
||||
}
|
||||
|
||||
private XContentSource toXContentSource(SearchInput.Result result) throws IOException {
|
||||
@ -387,7 +387,7 @@ public class SearchInputIT extends ESIntegTestCase {
|
||||
|
||||
@Override
|
||||
public ScriptContext.Plugin getCustomScriptContexts() {
|
||||
return ScriptServiceProxy.INSTANCE;
|
||||
return WatcherScript.CTX_PLUGIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.search.suggest.Suggesters;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.common.text.TextTemplate;
|
||||
import org.elasticsearch.xpack.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.xpack.watcher.condition.always.ExecutableAlwaysCondition;
|
||||
@ -40,7 +39,7 @@ import org.elasticsearch.xpack.watcher.execution.TriggeredExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.input.simple.ExecutableSimpleInput;
|
||||
import org.elasticsearch.xpack.watcher.input.simple.SimpleInput;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.support.init.proxy.WatcherClientProxy;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateRequest;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService;
|
||||
@ -348,7 +347,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
||||
}
|
||||
if (templateName != null) {
|
||||
assertThat(executable.transform().getRequest().getTemplate(),
|
||||
equalTo(Script.file("template1").build()));
|
||||
equalTo(WatcherScript.file("template1").build()));
|
||||
}
|
||||
SearchSourceBuilder source = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
|
||||
assertThat(executable.transform().getRequest().getRequest().source(), equalTo(source));
|
||||
@ -381,7 +380,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.inline(templateQuery).lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.inline(templateQuery).lang("mustache").params(params).build();
|
||||
SearchRequest request = client().prepareSearch().setSearchType(ExecutableSearchTransform.DEFAULT_SEARCH_TYPE)
|
||||
.setIndices("test-search-index").request();
|
||||
|
||||
@ -415,7 +414,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.indexed("test-script").lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.indexed("test-script").lang("mustache").params(params).build();
|
||||
|
||||
SearchRequest request = client()
|
||||
.prepareSearch()
|
||||
@ -441,7 +440,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.file("test_disk_template").lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.file("test_disk_template").lang("mustache").params(params).build();
|
||||
SearchRequest request = client().prepareSearch().setSearchType(ExecutableSearchTransform.DEFAULT_SEARCH_TYPE)
|
||||
.setIndices("test-search-index").request();
|
||||
|
||||
@ -504,7 +503,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
||||
timeValueSeconds(5));
|
||||
}
|
||||
|
||||
private SearchTransform.Result executeSearchTransform(SearchRequest request, Script template, WatchExecutionContext ctx)
|
||||
private SearchTransform.Result executeSearchTransform(SearchRequest request, WatcherScript template, WatchExecutionContext ctx)
|
||||
throws IOException {
|
||||
createIndex("test-search-index");
|
||||
ensureGreen("test-search-index");
|
||||
@ -519,15 +518,15 @@ public class SearchTransformIT extends ESIntegTestCase {
|
||||
protected WatcherSearchTemplateService watcherSearchTemplateService() {
|
||||
String master = internalCluster().getMasterName();
|
||||
return new WatcherSearchTemplateService(internalCluster().clusterService(master).getSettings(),
|
||||
ScriptServiceProxy.of(internalCluster().getInstance(ScriptService.class, master)),
|
||||
internalCluster().getInstance(ScriptService.class, master),
|
||||
internalCluster().getInstance(IndicesQueriesRegistry.class, master),
|
||||
internalCluster().getInstance(AggregatorParsers.class, master),
|
||||
internalCluster().getInstance(Suggesters.class, master)
|
||||
);
|
||||
}
|
||||
|
||||
protected ScriptServiceProxy scriptService() {
|
||||
return ScriptServiceProxy.of(internalCluster().getInstance(ScriptService.class));
|
||||
protected ScriptService scriptService() {
|
||||
return internalCluster().getInstance(ScriptService.class);
|
||||
}
|
||||
|
||||
private static Map<String, Object> doc(String date, String value) {
|
||||
@ -551,7 +550,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
||||
|
||||
@Override
|
||||
public ScriptContext.Plugin getCustomScriptContexts() {
|
||||
return ScriptServiceProxy.INSTANCE;
|
||||
return WatcherScript.CTX_PLUGIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,13 @@ package org.elasticsearch.messy.tests;
|
||||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.search.SearchPhaseExecutionException;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.indices.TermsLookup;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.Template;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.mustache.MustachePlugin;
|
||||
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
|
||||
import org.elasticsearch.script.mustache.TemplateQueryBuilder;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
@ -25,7 +24,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.elasticsearch.script.ScriptService.ScriptType.INLINE;
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -109,7 +107,7 @@ public class SecurityCachePermissionIT extends SecurityIntegTestCase {
|
||||
|
||||
//Template template = new Template(source, INLINE, MustacheScriptEngineService.NAME, null, singletonMap("name", "token"));
|
||||
SearchResponse response = client().prepareSearch("data").setTypes("a")
|
||||
.setQuery(QueryBuilders.templateQuery(source, singletonMap("name", "token")))
|
||||
.setQuery(new TemplateQueryBuilder(source, ScriptService.ScriptType.INLINE, singletonMap("name", "token")))
|
||||
.execute().actionGet();
|
||||
assertThat(response.isTimedOut(), is(false));
|
||||
assertThat(response.getHits().hits().length, is(1));
|
||||
@ -119,7 +117,7 @@ public class SecurityCachePermissionIT extends SecurityIntegTestCase {
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(READ_ONE_IDX_USER,
|
||||
new SecuredString("changeme".toCharArray()))))
|
||||
.prepareSearch("data").setTypes("a")
|
||||
.setQuery(QueryBuilders.templateQuery(source, singletonMap("name", "token")))
|
||||
.setQuery(new TemplateQueryBuilder(source, ScriptService.ScriptType.INLINE, singletonMap("name", "token")))
|
||||
.execute().actionGet());
|
||||
assertThat(e.toString(), containsString("ElasticsearchSecurityException[action"));
|
||||
assertThat(e.toString(), containsString("unauthorized"));
|
||||
|
@ -7,7 +7,7 @@ dependencies {
|
||||
integTest {
|
||||
cluster {
|
||||
setting 'script.inline', 'true'
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
extraConfigFile 'x-pack/roles.yml', 'roles.yml'
|
||||
[
|
||||
test_admin: 'superuser',
|
||||
|
@ -14,7 +14,7 @@ project.sourceSets.test.output.dir(outputDir, builtBy: copyXPackPluginProps)
|
||||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setupCommand 'setupDummyUser',
|
||||
'bin/x-pack/users', 'useradd', 'test_user', '-p', 'changeme', '-r', 'superuser'
|
||||
setupCommand 'setupTransportClientUser',
|
||||
|
@ -13,6 +13,7 @@ import org.elasticsearch.client.transport.TransportClient;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.transport.MockTransportClient;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
@ -115,6 +116,6 @@ public class SecurityTransportClientIT extends ESIntegTestCase {
|
||||
.put("cluster.name", clusterName)
|
||||
.build();
|
||||
|
||||
return TransportClient.builder().settings(settings).addPlugin(XPackPlugin.class).build().addTransportAddress(publishAddress);
|
||||
return new MockTransportClient(settings, XPackPlugin.class).addTransportAddress(publishAddress);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ task buildZip(type:Zip, dependsOn: [jar]) {
|
||||
|
||||
task integTest(type: org.elasticsearch.gradle.test.RestIntegTestTask, dependsOn: buildZip) {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.security.authc.realms.custom.order', '0'
|
||||
setting 'xpack.security.authc.realms.custom.type', 'custom'
|
||||
setting 'xpack.security.authc.realms.esusers.order', '1'
|
||||
|
@ -7,14 +7,27 @@ package org.elasticsearch.example;
|
||||
|
||||
import org.elasticsearch.example.realm.CustomAuthenticationFailureHandler;
|
||||
import org.elasticsearch.example.realm.CustomRealm;
|
||||
import org.elasticsearch.example.realm.CustomRealmFactory;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationModule;
|
||||
import org.elasticsearch.xpack.extensions.XPackExtension;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class ExampleRealmExtension extends XPackExtension {
|
||||
|
||||
static {
|
||||
// check that the extension's policy works.
|
||||
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||
System.getSecurityManager().checkPrintJobAccess();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "custom realm example";
|
||||
@ -26,12 +39,16 @@ public class ExampleRealmExtension extends XPackExtension {
|
||||
}
|
||||
|
||||
public void onModule(AuthenticationModule authenticationModule) {
|
||||
authenticationModule.addCustomRealm(CustomRealm.TYPE, CustomRealmFactory.class);
|
||||
authenticationModule.setAuthenticationFailureHandler(CustomAuthenticationFailureHandler.class);
|
||||
// check that the extension's policy works.
|
||||
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||
System.getSecurityManager().checkPrintJobAccess();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Realm.Factory> getRealms() {
|
||||
return Collections.singletonMap(CustomRealm.TYPE, CustomRealm::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getRestHeaders() {
|
||||
return Arrays.asList(CustomRealm.USER_HEADER, CustomRealm.PW_HEADER);
|
||||
}
|
||||
}
|
||||
|
@ -13,12 +13,12 @@ import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
|
||||
public class CustomRealm extends Realm<UsernamePasswordToken> {
|
||||
public class CustomRealm extends Realm {
|
||||
|
||||
public static final String TYPE = "custom";
|
||||
|
||||
static final String USER_HEADER = "User";
|
||||
static final String PW_HEADER = "Password";
|
||||
public static final String USER_HEADER = "User";
|
||||
public static final String PW_HEADER = "Password";
|
||||
|
||||
static final String KNOWN_USER = "custom_user";
|
||||
static final String KNOWN_PW = "changeme";
|
||||
@ -46,7 +46,8 @@ public class CustomRealm extends Realm<UsernamePasswordToken> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public User authenticate(UsernamePasswordToken token) {
|
||||
public User authenticate(AuthenticationToken authToken) {
|
||||
UsernamePasswordToken token = (UsernamePasswordToken)authToken;
|
||||
final String actualUser = token.principal();
|
||||
if (KNOWN_USER.equals(actualUser) && SecuredString.constantTimeEquals(token.credentials(), KNOWN_PW)) {
|
||||
return new User(actualUser, ROLES);
|
||||
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* 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.example.realm;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
|
||||
public class CustomRealmFactory extends Realm.Factory<CustomRealm> {
|
||||
|
||||
@Inject
|
||||
public CustomRealmFactory(RestController controller) {
|
||||
super(CustomRealm.TYPE, false);
|
||||
controller.registerRelevantHeaders(CustomRealm.USER_HEADER, CustomRealm.PW_HEADER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomRealm create(RealmConfig config) {
|
||||
return new CustomRealm(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomRealm createDefault(String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -20,7 +20,9 @@ import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -77,7 +79,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
||||
.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()) {
|
||||
try (TransportClient client = new XPackTransportClient(settings)) {
|
||||
client.addTransportAddress(publishAddress);
|
||||
ClusterHealthResponse response = client.admin().cluster().prepareHealth().execute().actionGet();
|
||||
assertThat(response.isTimedOut(), is(false));
|
||||
@ -97,7 +99,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
||||
.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()) {
|
||||
try (TransportClient client = new XPackTransportClient(settings)) {
|
||||
client.addTransportAddress(publishAddress);
|
||||
client.admin().cluster().prepareHealth().execute().actionGet();
|
||||
fail("authentication failure should have resulted in a NoNodesAvailableException");
|
||||
|
@ -7,7 +7,7 @@ dependencies {
|
||||
integTest {
|
||||
cluster {
|
||||
setting 'script.inline', 'true'
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
extraConfigFile 'x-pack/roles.yml', 'roles.yml'
|
||||
[
|
||||
test_admin: 'superuser',
|
||||
|
@ -118,6 +118,13 @@ public class MigrateToolIT extends MigrateToolTestCase {
|
||||
String token = basicAuthHeaderValue("bob", new SecuredString("changeme".toCharArray()));
|
||||
// Create "index1" index and try to search from it as "bob"
|
||||
client.filterWithHeader(Collections.singletonMap("Authorization", token)).admin().indices().prepareCreate("index1").get();
|
||||
// Wait for the index to be ready so it doesn't fail if no shards are initialized
|
||||
client.admin().cluster().health(Requests.clusterHealthRequest("index1")
|
||||
.timeout(TimeValue.timeValueSeconds(30))
|
||||
.waitForYellowStatus()
|
||||
.waitForEvents(Priority.LANGUID)
|
||||
.waitForRelocatingShards(0))
|
||||
.actionGet();
|
||||
SearchResponse searchResp = client.filterWithHeader(Collections.singletonMap("Authorization", token)).prepareSearch("index1").get();
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,8 @@ import org.elasticsearch.common.logging.ESLoggerFactory;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.node.internal.InternalSettingsPreparer;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
@ -25,10 +24,8 @@ import org.junit.BeforeClass;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomAsciiOfLength;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
/**
|
||||
@ -45,6 +42,7 @@ import static org.hamcrest.Matchers.notNullValue;
|
||||
* your test.
|
||||
*/
|
||||
@LuceneTestCase.SuppressSysoutChecks(bugUrl = "we log a lot on purpose")
|
||||
@ESIntegTestCase.SuppressLocalMode
|
||||
public abstract class MigrateToolTestCase extends LuceneTestCase {
|
||||
|
||||
/**
|
||||
@ -77,13 +75,9 @@ public abstract class MigrateToolTestCase extends LuceneTestCase {
|
||||
.put("client.transport.ignore_cluster_name", true)
|
||||
.put("path.home", tempDir)
|
||||
.put(Security.USER_SETTING.getKey(), "transport_user:changeme")
|
||||
.put("node.mode", "network") // we require network here!
|
||||
.build();
|
||||
|
||||
TransportClient.Builder transportClientBuilder = TransportClient.builder()
|
||||
.addPlugin(XPackPlugin.class)
|
||||
.settings(clientSettings);
|
||||
TransportClient client = transportClientBuilder.build().addTransportAddresses(transportAddresses);
|
||||
TransportClient client = new XPackTransportClient(clientSettings).addTransportAddresses(transportAddresses);
|
||||
|
||||
logger.info("--> Elasticsearch Java TransportClient started");
|
||||
|
||||
|
@ -15,7 +15,7 @@ integTest {
|
||||
dependsOn copyGraphRestTests
|
||||
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
extraConfigFile 'x-pack/roles.yml', 'roles.yml'
|
||||
setupCommand 'setupTestAdminUser',
|
||||
'bin/x-pack/users', 'useradd', 'test_admin', '-p', 'changeme', '-r', 'superuser'
|
||||
|
@ -17,7 +17,7 @@ subprojects {
|
||||
|
||||
cluster {
|
||||
systemProperty 'es.logger.level', 'TRACE'
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.monitoring.collection.interval', '3s'
|
||||
extraConfigFile 'x-pack/roles.yml', '../roles.yml'
|
||||
setupCommand 'setupTestAdminUser',
|
||||
|
@ -147,7 +147,7 @@ processTestResources.dependsOn(
|
||||
ext.pluginsCount = 1 // we install xpack explicitly
|
||||
project.rootProject.subprojects.findAll { it.path.startsWith(':plugins:') }.each { subproj ->
|
||||
// need to get a non-decorated project object, so must re-lookup the project by path
|
||||
integTest.cluster.plugin(subproj.name, project(subproj.path))
|
||||
integTest.cluster.plugin(subproj.path)
|
||||
pluginsCount += 1
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ integTest {
|
||||
setting 'xpack.security.ssl.keystore.path', nodeKeystore.name
|
||||
setting 'xpack.security.ssl.keystore.password', 'keypass'
|
||||
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
|
||||
// copy keystores into config/
|
||||
extraConfigFile nodeKeystore.name, nodeKeystore
|
||||
|
@ -9,11 +9,12 @@ import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
|
||||
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
|
||||
import org.elasticsearch.common.io.PathUtils;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.security.transport.netty.SecurityNettyTransport;
|
||||
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3Transport;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.junit.After;
|
||||
@ -49,7 +50,6 @@ public class SmokeTestMonitoringWithSecurityIT extends ESIntegTestCase {
|
||||
private static final String USER = "test_user";
|
||||
private static final String PASS = "changeme";
|
||||
private static final String KEYSTORE_PASS = "keypass";
|
||||
|
||||
private static final String MONITORING_PATTERN = ".monitoring-*";
|
||||
|
||||
@Override
|
||||
@ -61,9 +61,10 @@ public class SmokeTestMonitoringWithSecurityIT extends ESIntegTestCase {
|
||||
protected Settings externalClusterClientSettings() {
|
||||
return Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), USER + ":" + PASS)
|
||||
.put(SecurityNettyTransport.SSL_SETTING.getKey(), true)
|
||||
.put(SecurityNetty3Transport.SSL_SETTING.getKey(), true)
|
||||
.put("xpack.security.ssl.keystore.path", clientKeyStore)
|
||||
.put("xpack.security.ssl.keystore.password", KEYSTORE_PASS)
|
||||
.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -9,13 +9,13 @@ dependencies {
|
||||
ext.pluginsCount = 1 // we install xpack explicitly
|
||||
project.rootProject.subprojects.findAll { it.path.startsWith(':plugins:') }.each { subproj ->
|
||||
// need to get a non-decorated project object, so must re-lookup the project by path
|
||||
integTest.cluster.plugin(subproj.name, project(subproj.path))
|
||||
integTest.cluster.plugin(subproj.path)
|
||||
pluginsCount += 1
|
||||
}
|
||||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
|
||||
setupCommand 'setupDummyUser',
|
||||
'bin/x-pack/users', 'useradd', 'test_user', '-p', 'changeme', '-r', 'superuser'
|
||||
|
@ -7,7 +7,7 @@ dependencies {
|
||||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'script.inline', 'true'
|
||||
setting 'xpack.security.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
|
@ -7,7 +7,7 @@ dependencies {
|
||||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.security.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
setting 'http.port', '9400'
|
||||
|
@ -6,37 +6,31 @@
|
||||
package org.elasticsearch.smoketest;
|
||||
|
||||
import com.fasterxml.jackson.core.io.JsonStringEncoder;
|
||||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineService;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.common.text.DefaultTextTemplateEngine;
|
||||
import org.elasticsearch.xpack.common.text.TextTemplate;
|
||||
import org.elasticsearch.xpack.common.text.TextTemplateEngine;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.junit.Before;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
@ -50,7 +44,7 @@ public class WatcherTemplateTests extends ESTestCase {
|
||||
Settings setting = Settings.builder().put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING, true).build();
|
||||
Environment environment = Mockito.mock(Environment.class);
|
||||
ResourceWatcherService resourceWatcherService = Mockito.mock(ResourceWatcherService.class);
|
||||
ScriptContextRegistry registry = new ScriptContextRegistry(Collections.singletonList(ScriptServiceProxy.INSTANCE));
|
||||
ScriptContextRegistry registry = new ScriptContextRegistry(Collections.singletonList(WatcherScript.CTX_PLUGIN));
|
||||
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(
|
||||
Collections.singleton(new MustacheScriptEngineService(setting))
|
||||
@ -58,7 +52,7 @@ public class WatcherTemplateTests extends ESTestCase {
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, registry);
|
||||
ScriptService scriptService = new ScriptService(setting, environment, resourceWatcherService, scriptEngineRegistry,
|
||||
registry, scriptSettings);
|
||||
engine = new DefaultTextTemplateEngine(Settings.EMPTY, ScriptServiceProxy.of(scriptService));
|
||||
engine = new DefaultTextTemplateEngine(Settings.EMPTY, scriptService);
|
||||
}
|
||||
|
||||
public void testEscaping() throws Exception {
|
||||
|
@ -7,7 +7,7 @@ dependencies {
|
||||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'script.inline', 'true'
|
||||
setting 'xpack.security.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
|
@ -19,7 +19,7 @@ integTest {
|
||||
'getting_started/10_monitor_cluster_health/Getting started - Monitor cluster health'].join(',')
|
||||
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
extraConfigFile 'x-pack/roles.yml', 'roles.yml'
|
||||
setupCommand 'setupTestAdminUser',
|
||||
'bin/x-pack/users', 'useradd', 'test_admin', '-p', 'changeme', '-r', 'superuser'
|
||||
|
14
elasticsearch/qa/smoke-test-watcher/build.gradle
Normal file
14
elasticsearch/qa/smoke-test-watcher/build.gradle
Normal file
@ -0,0 +1,14 @@
|
||||
apply plugin: 'elasticsearch.rest-test'
|
||||
|
||||
dependencies {
|
||||
testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime')
|
||||
}
|
||||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.security.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
setting 'http.port', '9400'
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.smoketest;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
/** Runs rest tests against external cluster */
|
||||
public class WatcherGettingStartedIT extends ESRestTestCase {
|
||||
|
||||
public WatcherGettingStartedIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void startWatcher() throws Exception {
|
||||
getAdminExecutionContext().callApi("xpack.watcher.start", emptyMap(), emptyList(), emptyMap());
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopWatcher() throws Exception {
|
||||
getAdminExecutionContext().callApi("xpack.watcher.stop", emptyMap(), emptyList(), emptyMap());
|
||||
}
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
# This test has been moved out of the regular tests as it requires Elasticsearch to run on port 9400
|
||||
# That is a no-go for the clients testing, who could start Elasticsearch on arbitrary ports
|
||||
#
|
||||
---
|
||||
setup:
|
||||
- do:
|
@ -27,8 +27,9 @@ dependencies {
|
||||
testCompile project(':x-plugins:elasticsearch:license:licensor')
|
||||
|
||||
// security deps
|
||||
compile project(path: ':modules:transport-netty3', configuration: 'runtime')
|
||||
compile 'dk.brics.automaton:automaton:1.11-8'
|
||||
compile 'com.unboundid:unboundid-ldapsdk:2.3.8'
|
||||
compile 'com.unboundid:unboundid-ldapsdk:3.1.1'
|
||||
compile 'org.bouncycastle:bcprov-jdk15on:1.54'
|
||||
compile 'org.bouncycastle:bcpkix-jdk15on:1.54'
|
||||
testCompile 'com.google.jimfs:jimfs:1.1'
|
||||
|
@ -9,6 +9,7 @@ import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.inject.util.Providers;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.plugins.ActionPlugin;
|
||||
@ -43,15 +44,12 @@ public class Graph extends Plugin implements ActionPlugin {
|
||||
}
|
||||
|
||||
public Collection<Module> createGuiceModules() {
|
||||
return Collections.singletonList(new GraphModule(enabled, transportClientMode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends LifecycleComponent>> getGuiceServiceClasses() {
|
||||
if (enabled == false|| transportClientMode) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.singletonList(GraphLicensee.class);
|
||||
return Collections.singletonList(b -> {
|
||||
XPackPlugin.bindFeatureSet(b, GraphFeatureSet.class);
|
||||
if (transportClientMode) {
|
||||
b.bind(GraphLicensee.class).toProvider(Providers.of(null));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,21 +6,17 @@
|
||||
package org.elasticsearch.xpack.graph;
|
||||
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.core.License.OperationMode;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
|
||||
public class GraphLicensee extends AbstractLicenseeComponent<GraphLicensee> {
|
||||
public class GraphLicensee extends AbstractLicenseeComponent {
|
||||
|
||||
public static final String ID = Graph.NAME;
|
||||
|
||||
@Inject
|
||||
public GraphLicensee(Settings settings, LicenseeRegistry clientService) {
|
||||
super(settings, ID, clientService);
|
||||
public GraphLicensee(Settings settings) {
|
||||
super(settings, ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -31,17 +27,15 @@ public class GraphLicensee extends AbstractLicenseeComponent<GraphLicensee> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] acknowledgmentMessages(License currentLicense, License newLicense) {
|
||||
switch (newLicense.operationMode()) {
|
||||
public String[] acknowledgmentMessages(OperationMode currentMode, OperationMode newMode) {
|
||||
switch (newMode) {
|
||||
case BASIC:
|
||||
case STANDARD:
|
||||
case GOLD:
|
||||
if (currentLicense != null) {
|
||||
switch (currentLicense.operationMode()) {
|
||||
case TRIAL:
|
||||
case PLATINUM:
|
||||
return new String[] { "Graph will be disabled" };
|
||||
}
|
||||
switch (currentMode) {
|
||||
case TRIAL:
|
||||
case PLATINUM:
|
||||
return new String[] { "Graph will be disabled" };
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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.xpack.graph;
|
||||
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.inject.util.Providers;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class GraphModule extends AbstractModule {
|
||||
|
||||
private final boolean enabled;
|
||||
private final boolean transportClientNode;
|
||||
|
||||
public GraphModule(boolean enabled, boolean transportClientNode) {
|
||||
this.enabled = enabled;
|
||||
this.transportClientNode = transportClientNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
XPackPlugin.bindFeatureSet(binder(), GraphFeatureSet.class);
|
||||
if (enabled && transportClientNode == false) {
|
||||
bind(GraphLicensee.class).asEagerSingleton();
|
||||
} else {
|
||||
bind(GraphLicensee.class).toProvider(Providers.of(null));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -14,114 +14,81 @@ import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class LicenseTests extends AbstractLicenseeTestCase {
|
||||
|
||||
private SimpleLicenseeRegistry licenseeRegistry = new SimpleLicenseeRegistry();
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY);
|
||||
|
||||
public void testPlatinumTrialLicenseCanDoEverything() throws Exception {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testBasicLicenseIsDisabled() throws Exception {
|
||||
licenseeRegistry.setOperationMode(OperationMode.BASIC);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
setOperationMode(graphLicensee, OperationMode.BASIC);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testStandardLicenseIsDisabled() throws Exception {
|
||||
licenseeRegistry.setOperationMode(OperationMode.STANDARD);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
setOperationMode(graphLicensee, OperationMode.STANDARD);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testNoLicenseDoesNotWork() {
|
||||
licenseeRegistry.setOperationMode(OperationMode.BASIC);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
||||
setOperationMode(graphLicensee, OperationMode.BASIC);
|
||||
disable(graphLicensee);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testExpiredPlatinumTrialLicenseIsRestricted() throws Exception {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
||||
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
|
||||
disable(graphLicensee);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testUpgradingFromBasicLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(OperationMode.BASIC);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
setOperationMode(graphLicensee, OperationMode.BASIC);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testDowngradingToBasicLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(OperationMode.BASIC);
|
||||
setOperationMode(graphLicensee, OperationMode.BASIC);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testUpgradingFromStandardLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(OperationMode.STANDARD);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
setOperationMode(graphLicensee, OperationMode.STANDARD);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testDowngradingToStandardLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(OperationMode.STANDARD);
|
||||
setOperationMode(graphLicensee, OperationMode.STANDARD);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testDowngradingToGoldLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(OperationMode.GOLD);
|
||||
setOperationMode(graphLicensee, OperationMode.GOLD);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testUpgradingExpiredLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
||||
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
|
||||
disable(graphLicensee);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,11 @@ package org.elasticsearch.license.plugin;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.delete.TransportDeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseAction;
|
||||
@ -26,6 +26,13 @@ import org.elasticsearch.license.plugin.rest.RestGetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.rest.RestPutLicenseAction;
|
||||
import org.elasticsearch.plugins.ActionPlugin;
|
||||
import org.elasticsearch.rest.RestHandler;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.graph.GraphLicensee;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
|
||||
import org.elasticsearch.xpack.security.SecurityLicenseState;
|
||||
import org.elasticsearch.xpack.security.SecurityLicensee;
|
||||
import org.elasticsearch.xpack.support.clock.Clock;
|
||||
import org.elasticsearch.xpack.watcher.WatcherLicensee;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -40,19 +47,24 @@ import static org.elasticsearch.xpack.XPackPlugin.transportClientMode;
|
||||
public class Licensing implements ActionPlugin {
|
||||
|
||||
public static final String NAME = "license";
|
||||
private final boolean isTransportClient;
|
||||
protected final Settings settings;
|
||||
protected final boolean isTransportClient;
|
||||
private final boolean isTribeNode;
|
||||
|
||||
static {
|
||||
MetaData.registerPrototype(LicensesMetaData.TYPE, LicensesMetaData.PROTO);
|
||||
}
|
||||
|
||||
@Inject
|
||||
public Licensing(Settings settings) {
|
||||
this.settings = settings;
|
||||
isTransportClient = transportClientMode(settings);
|
||||
isTribeNode = isTribeNode(settings);
|
||||
}
|
||||
|
||||
public Collection<Module> nodeModules() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActionHandler<? extends ActionRequest<?>, ? extends ActionResponse>> getActions() {
|
||||
if (isTribeNode) {
|
||||
@ -73,18 +85,18 @@ public class Licensing implements ActionPlugin {
|
||||
RestDeleteLicenseAction.class);
|
||||
}
|
||||
|
||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||
if (isTransportClient == false && isTribeNode == false) {
|
||||
return Collections.<Class<? extends LifecycleComponent>>singletonList(LicensesService.class);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
public Collection<Object> createComponents(ClusterService clusterService, Clock clock, Environment environment,
|
||||
ResourceWatcherService resourceWatcherService,
|
||||
SecurityLicenseState securityLicenseState) {
|
||||
SecurityLicensee securityLicensee = new SecurityLicensee(settings, securityLicenseState);
|
||||
WatcherLicensee watcherLicensee = new WatcherLicensee(settings);
|
||||
MonitoringLicensee monitoringLicensee = new MonitoringLicensee(settings);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(settings);
|
||||
LicensesService licensesService = new LicensesService(settings, clusterService, clock,
|
||||
environment, resourceWatcherService,
|
||||
Arrays.asList(securityLicensee, watcherLicensee, monitoringLicensee, graphLicensee));
|
||||
|
||||
public Collection<Module> nodeModules() {
|
||||
if (isTransportClient == false && isTribeNode == false) {
|
||||
return Collections.<Module>singletonList(new LicensingModule());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
return Arrays.asList(licensesService, securityLicenseState, securityLicensee, watcherLicensee, monitoringLicensee, graphLicensee);
|
||||
}
|
||||
|
||||
public List<Setting<?>> getSettings() {
|
||||
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* 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.license.plugin;
|
||||
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.license.core.LicenseVerifier;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
|
||||
public class LicensingModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(LicenseVerifier.class).asEagerSingleton();
|
||||
bind(LicensesService.class).asEagerSingleton();
|
||||
bind(LicenseeRegistry.class).to(LicensesService.class);
|
||||
bind(LicensesManagerService.class).to(LicensesService.class);
|
||||
}
|
||||
|
||||
}
|
@ -9,28 +9,28 @@ import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.support.ActionFilters;
|
||||
import org.elasticsearch.action.support.master.TransportMasterNodeReadAction;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
public class TransportGetLicenseAction extends TransportMasterNodeReadAction<GetLicenseRequest, GetLicenseResponse> {
|
||||
|
||||
private final LicensesManagerService licensesManagerService;
|
||||
private final LicensesService licensesService;
|
||||
|
||||
@Inject
|
||||
public TransportGetLicenseAction(Settings settings, TransportService transportService, ClusterService clusterService,
|
||||
LicensesManagerService licensesManagerService, ThreadPool threadPool, ActionFilters actionFilters,
|
||||
LicensesService licensesService, ThreadPool threadPool, ActionFilters actionFilters,
|
||||
IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||
super(settings, GetLicenseAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver,
|
||||
GetLicenseRequest::new);
|
||||
this.licensesManagerService = licensesManagerService;
|
||||
this.licensesService = licensesService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -51,6 +51,6 @@ public class TransportGetLicenseAction extends TransportMasterNodeReadAction<Get
|
||||
@Override
|
||||
protected void masterOperation(final GetLicenseRequest request, ClusterState state, final ActionListener<GetLicenseResponse>
|
||||
listener) throws ElasticsearchException {
|
||||
listener.onResponse(new GetLicenseResponse(licensesManagerService.getLicense()));
|
||||
listener.onResponse(new GetLicenseResponse(licensesService.getLicense()));
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.core;
|
||||
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
||||
@ -14,33 +15,17 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
/**
|
||||
* A supporting base class for injectable Licensee components.
|
||||
*/
|
||||
public abstract class AbstractLicenseeComponent<T extends AbstractLicenseeComponent<T>> extends AbstractLifecycleComponent
|
||||
implements Licensee {
|
||||
public abstract class AbstractLicenseeComponent extends AbstractComponent implements Licensee {
|
||||
|
||||
private final String id;
|
||||
private final LicenseeRegistry clientService;
|
||||
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
// we initialize the licensee state to enabled with trial operation mode
|
||||
protected volatile Status status = Status.ENABLED;
|
||||
|
||||
protected AbstractLicenseeComponent(Settings settings, String id, LicenseeRegistry clientService) {
|
||||
protected AbstractLicenseeComponent(Settings settings, String id) {
|
||||
super(settings);
|
||||
this.id = id;
|
||||
this.clientService = clientService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() {
|
||||
clientService.register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doClose() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -8,8 +8,6 @@ package org.elasticsearch.license.plugin.core;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.xpack.scheduler.SchedulerEngine;
|
||||
|
||||
import static org.elasticsearch.license.plugin.core.LicensesService.GRACE_PERIOD_DURATION;
|
||||
import static org.elasticsearch.license.plugin.core.LicensesService.getLicenseState;
|
||||
|
||||
public class LicenseSchedule implements SchedulerEngine.Schedule {
|
||||
|
||||
@ -22,12 +20,12 @@ public class LicenseSchedule implements SchedulerEngine.Schedule {
|
||||
@Override
|
||||
public long nextScheduledTimeAfter(long startTime, long time) {
|
||||
long nextScheduledTime = -1;
|
||||
switch (getLicenseState(license, time)) {
|
||||
switch (LicenseState.resolve(license, time)) {
|
||||
case ENABLED:
|
||||
nextScheduledTime = license.expiryDate();
|
||||
break;
|
||||
case GRACE_PERIOD:
|
||||
nextScheduledTime = license.expiryDate() + GRACE_PERIOD_DURATION.getMillis();
|
||||
nextScheduledTime = license.expiryDate() + LicenseState.GRACE_PERIOD_DURATION.getMillis();
|
||||
break;
|
||||
case DISABLED:
|
||||
if (license.issueDate() > time) {
|
||||
@ -42,4 +40,4 @@ public class LicenseSchedule implements SchedulerEngine.Schedule {
|
||||
}
|
||||
return nextScheduledTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,11 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.core;
|
||||
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.license.core.License;
|
||||
|
||||
import static org.elasticsearch.license.plugin.core.LicensesService.days;
|
||||
|
||||
/**
|
||||
* States of a registered licensee
|
||||
* based on the current license
|
||||
@ -38,5 +43,26 @@ public enum LicenseState {
|
||||
* changes to {@link #ENABLED}, otherwise
|
||||
* remains unchanged
|
||||
*/
|
||||
DISABLED
|
||||
DISABLED;
|
||||
|
||||
/**
|
||||
* Duration of grace period after a license has expired
|
||||
*/
|
||||
public static final TimeValue GRACE_PERIOD_DURATION = days(7);
|
||||
|
||||
public static LicenseState resolve(final License license, long time) {
|
||||
if (license == null) {
|
||||
return DISABLED;
|
||||
}
|
||||
if (license.issueDate() > time) {
|
||||
return DISABLED;
|
||||
}
|
||||
if (license.expiryDate() > time) {
|
||||
return ENABLED;
|
||||
}
|
||||
if ((license.expiryDate() + GRACE_PERIOD_DURATION.getMillis()) > time) {
|
||||
return GRACE_PERIOD;
|
||||
}
|
||||
return DISABLED;
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,10 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.core;
|
||||
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.core.License.OperationMode;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
public interface Licensee {
|
||||
|
||||
@ -26,11 +26,10 @@ public interface Licensee {
|
||||
|
||||
/**
|
||||
* Messages to be returned when
|
||||
* installing <code>newLicense</code>
|
||||
* when <code>currentLicense</code> is
|
||||
* active
|
||||
* changing from current operation mode
|
||||
* to new operation mode
|
||||
*/
|
||||
String[] acknowledgmentMessages(License currentLicense, License newLicense);
|
||||
String[] acknowledgmentMessages(OperationMode currentMode, OperationMode newMode);
|
||||
|
||||
/**
|
||||
* Notifies when a new license is activated
|
||||
@ -85,6 +84,20 @@ public interface Licensee {
|
||||
return licenseState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Status status = (Status) o;
|
||||
return Objects.equals(mode, status.mode) && Objects.equals(licenseState, status.licenseState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mode, licenseState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (licenseState) {
|
||||
|
@ -1,14 +0,0 @@
|
||||
/*
|
||||
* 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.license.plugin.core;
|
||||
|
||||
public interface LicenseeRegistry {
|
||||
|
||||
/**
|
||||
* Registers a licensee for license notifications
|
||||
*/
|
||||
void register(Licensee licensee);
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* 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.license.plugin.core;
|
||||
|
||||
import org.elasticsearch.license.core.License;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface LicensesManagerService {
|
||||
|
||||
/**
|
||||
* @return current {@link LicenseState}
|
||||
*/
|
||||
LicenseState licenseState();
|
||||
|
||||
/**
|
||||
* @return the currently active license, or {@code null} if no license is currently installed
|
||||
*/
|
||||
License getLicense();
|
||||
}
|
@ -15,29 +15,24 @@ import org.elasticsearch.cluster.ClusterStateListener;
|
||||
import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
||||
import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||
import org.elasticsearch.common.component.Lifecycle;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
|
||||
import org.elasticsearch.common.joda.Joda;
|
||||
import org.elasticsearch.common.logging.LoggerMessageFormat;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.gateway.GatewayService;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.core.LicenseVerifier;
|
||||
import org.elasticsearch.license.core.OperationModeFileWatcher;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.EmptyTransportResponseHandler;
|
||||
import org.elasticsearch.transport.TransportChannel;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.elasticsearch.transport.TransportRequestHandler;
|
||||
import org.elasticsearch.transport.TransportResponse;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.scheduler.SchedulerEngine;
|
||||
import org.elasticsearch.xpack.support.clock.Clock;
|
||||
|
||||
@ -48,42 +43,31 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Service responsible for managing {@link LicensesMetaData}
|
||||
* Interfaces through which this is exposed are:
|
||||
* - LicensesManagerService - responsible for managing signed and one-time-trial licenses
|
||||
* - LicensesClientService - responsible for listener registration of consumer plugin(s)
|
||||
* <p>
|
||||
* Registration Scheme:
|
||||
* <p>
|
||||
* A consumer plugin is registered with {@link LicenseeRegistry#register(Licensee)}
|
||||
* This method can be called at any time during the life-cycle of the consumer plugin.
|
||||
* If the listener can not be registered immediately, it is queued up and registered on the first clusterChanged event with
|
||||
* no {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK} block
|
||||
* Upon successful registration, the listeners are notified appropriately using the notification scheme
|
||||
* <p>
|
||||
* Notification Scheme:
|
||||
* <p>
|
||||
* All registered listeners are notified of the current license upon registration or when a new license is installed in the cluster state.
|
||||
* When a new license is notified as enabled to the registered listener, a notification is scheduled at the time of license expiry.
|
||||
* Registered listeners are notified using {@link #onUpdate(LicensesMetaData)}
|
||||
*/
|
||||
public class LicensesService extends AbstractLifecycleComponent implements ClusterStateListener, LicensesManagerService,
|
||||
LicenseeRegistry, SchedulerEngine.Listener {
|
||||
public class LicensesService extends AbstractLifecycleComponent implements ClusterStateListener, SchedulerEngine.Listener {
|
||||
|
||||
public static final String REGISTER_TRIAL_LICENSE_ACTION_NAME = "internal:plugin/license/cluster/register_trial_license";
|
||||
// pkg private for tests
|
||||
static final TimeValue TRIAL_LICENSE_DURATION = TimeValue.timeValueHours(30 * 24);
|
||||
|
||||
private final ClusterService clusterService;
|
||||
|
||||
private final TransportService transportService;
|
||||
|
||||
/**
|
||||
* Currently active consumers to notify to
|
||||
*/
|
||||
private final List<InternalLicensee> registeredLicensees = new CopyOnWriteArrayList<>();
|
||||
private final List<InternalLicensee> registeredLicensees;
|
||||
|
||||
/**
|
||||
* Currently active license
|
||||
@ -92,46 +76,39 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
private SchedulerEngine scheduler;
|
||||
private final Clock clock;
|
||||
|
||||
/**
|
||||
* File watcher for operation mode changes
|
||||
*/
|
||||
private final OperationModeFileWatcher operationModeFileWatcher;
|
||||
|
||||
/**
|
||||
* Callbacks to notify relative to license expiry
|
||||
*/
|
||||
private List<ExpirationCallback> expirationCallbacks = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Duration of generated trial license
|
||||
*/
|
||||
private TimeValue trialLicenseDuration = TimeValue.timeValueHours(30 * 24);
|
||||
|
||||
/**
|
||||
* Max number of nodes licensed by generated trial license
|
||||
*/
|
||||
private int trialLicenseMaxNodes = 1000;
|
||||
|
||||
/**
|
||||
* Duration of grace period after a license has expired
|
||||
*/
|
||||
public static final TimeValue GRACE_PERIOD_DURATION = days(7);
|
||||
|
||||
private static final String LICENSE_JOB = "licenseJob";
|
||||
public static final String LICENSE_JOB = "licenseJob";
|
||||
|
||||
private static final FormatDateTimeFormatter DATE_FORMATTER = Joda.forPattern("EEEE, MMMMM dd, yyyy", Locale.ROOT);
|
||||
|
||||
private static final String ACKNOWLEDGEMENT_HEADER = "This license update requires acknowledgement. To acknowledge the license, " +
|
||||
"please read the following messages and update the license again, this time with the \"acknowledge=true\" parameter:";
|
||||
|
||||
@Inject
|
||||
public LicensesService(Settings settings, ClusterService clusterService, TransportService transportService, Clock clock) {
|
||||
public LicensesService(Settings settings, ClusterService clusterService, Clock clock, Environment env,
|
||||
ResourceWatcherService resourceWatcherService, List<Licensee> registeredLicensees) {
|
||||
super(settings);
|
||||
this.clusterService = clusterService;
|
||||
this.transportService = transportService;
|
||||
if (DiscoveryNode.isMasterNode(settings)) {
|
||||
transportService.registerRequestHandler(REGISTER_TRIAL_LICENSE_ACTION_NAME, TransportRequest.Empty::new,
|
||||
ThreadPool.Names.SAME, new RegisterTrialLicenseRequestHandler());
|
||||
}
|
||||
populateExpirationCallbacks();
|
||||
this.clock = clock;
|
||||
this.scheduler = new SchedulerEngine(clock);
|
||||
this.registeredLicensees = registeredLicensees.stream().map(InternalLicensee::new).collect(Collectors.toList());
|
||||
this.operationModeFileWatcher = new OperationModeFileWatcher(resourceWatcherService,
|
||||
XPackPlugin.resolveConfigFile(env, "license_mode"), logger, () -> notifyLicensees(getLicense()));
|
||||
this.scheduler.register(this);
|
||||
populateExpirationCallbacks();
|
||||
}
|
||||
|
||||
private void populateExpirationCallbacks() {
|
||||
@ -256,7 +233,8 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
"override the current license?"});
|
||||
}
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
String[] listenerAcknowledgeMessages = licensee.acknowledgmentMessages(currentLicense, newLicense);
|
||||
String[] listenerAcknowledgeMessages = licensee.acknowledgmentMessages(
|
||||
currentLicense.operationMode(), newLicense.operationMode());
|
||||
if (listenerAcknowledgeMessages.length > 0) {
|
||||
acknowledgeMessages.put(licensee.id(), listenerAcknowledgeMessages);
|
||||
}
|
||||
@ -332,17 +310,14 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public LicenseState licenseState() {
|
||||
if (registeredLicensees.size() > 0) {
|
||||
return registeredLicensees.get(0).currentLicenseState;
|
||||
} else {
|
||||
final License license = getLicense(clusterService.state().metaData().custom(LicensesMetaData.TYPE));
|
||||
return getLicenseState(license, clock.millis());
|
||||
public Licensee.Status licenseeStatus() {
|
||||
final License license = getLicense();
|
||||
if (license == null) {
|
||||
return Licensee.Status.MISSING;
|
||||
}
|
||||
return new Licensee.Status(license.operationMode(), LicenseState.resolve(license, clock.millis()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public License getLicense() {
|
||||
final License license = getLicense(clusterService.state().metaData().custom(LicensesMetaData.TYPE));
|
||||
return license == LicensesMetaData.LICENSE_TOMBSTONE ? null : license;
|
||||
@ -354,7 +329,7 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
* has no signed/trial license
|
||||
*/
|
||||
private void registerTrialLicense() {
|
||||
clusterService.submitStateUpdateTask("generate trial license for [" + trialLicenseDuration + "]", new ClusterStateUpdateTask() {
|
||||
clusterService.submitStateUpdateTask("generate trial license for [" + TRIAL_LICENSE_DURATION + "]", new ClusterStateUpdateTask() {
|
||||
@Override
|
||||
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
|
||||
LicensesMetaData licensesMetaData = newState.metaData().custom(LicensesMetaData.TYPE);
|
||||
@ -376,7 +351,7 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
.issuedTo(clusterService.getClusterName().value())
|
||||
.maxNodes(trialLicenseMaxNodes)
|
||||
.issueDate(issueDate)
|
||||
.expiryDate(issueDate + trialLicenseDuration.getMillis());
|
||||
.expiryDate(issueDate + TRIAL_LICENSE_DURATION.getMillis());
|
||||
License trialLicense = TrialLicense.create(specBuilder);
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(trialLicense));
|
||||
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||
@ -396,6 +371,7 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
protected void doStart() throws ElasticsearchException {
|
||||
clusterService.add(this);
|
||||
scheduler.start(Collections.emptyList());
|
||||
registeredLicensees.forEach(x -> initLicensee(x.licensee));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -404,14 +380,12 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
scheduler.stop();
|
||||
// clear all handlers
|
||||
registeredLicensees.clear();
|
||||
|
||||
// clear current license
|
||||
currentLicense.set(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doClose() throws ElasticsearchException {
|
||||
transportService.removeHandler(REGISTER_TRIAL_LICENSE_ACTION_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -440,9 +414,10 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
}
|
||||
// auto-generate license if no licenses ever existed
|
||||
// this will trigger a subsequent cluster changed event
|
||||
if (prevLicensesMetaData == null
|
||||
&& (currentLicensesMetaData == null || currentLicensesMetaData.getLicense() == null)) {
|
||||
requestTrialLicense(currentClusterState);
|
||||
if (currentClusterState.getNodes().isLocalNodeElectedMaster() &&
|
||||
prevLicensesMetaData == null &&
|
||||
(currentLicensesMetaData == null || currentLicensesMetaData.getLicense() == null)) {
|
||||
registerTrialLicense();
|
||||
}
|
||||
} else if (logger.isDebugEnabled()) {
|
||||
logger.debug("skipped license notifications reason: [{}]", GatewayService.STATE_NOT_RECOVERED_BLOCK);
|
||||
@ -458,45 +433,22 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
}
|
||||
if (license != null) {
|
||||
logger.debug("notifying [{}] listeners", registeredLicensees.size());
|
||||
switch (getLicenseState(license, clock.millis())) {
|
||||
final LicenseState licenseState = LicenseState.resolve(license, clock.millis());
|
||||
Licensee.Status status = new Licensee.Status(license.operationMode(), licenseState);
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
licensee.onChange(status);
|
||||
}
|
||||
switch (status.getLicenseState()) {
|
||||
case ENABLED:
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
licensee.onChange(license, LicenseState.ENABLED);
|
||||
}
|
||||
logger.debug("license [{}] - valid", license.uid());
|
||||
break;
|
||||
logger.debug("license [{}] - valid", license.uid()); break;
|
||||
case GRACE_PERIOD:
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
licensee.onChange(license, LicenseState.GRACE_PERIOD);
|
||||
}
|
||||
logger.warn("license [{}] - grace", license.uid());
|
||||
break;
|
||||
logger.warn("license [{}] - grace", license.uid()); break;
|
||||
case DISABLED:
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
licensee.onChange(license, LicenseState.DISABLED);
|
||||
}
|
||||
logger.warn("license [{}] - expired", license.uid());
|
||||
break;
|
||||
logger.warn("license [{}] - expired", license.uid()); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LicenseState getLicenseState(final License license, long time) {
|
||||
if (license == null) {
|
||||
return LicenseState.DISABLED;
|
||||
}
|
||||
if (license.issueDate() > time) {
|
||||
return LicenseState.DISABLED;
|
||||
}
|
||||
if (license.expiryDate() > time) {
|
||||
return LicenseState.ENABLED;
|
||||
}
|
||||
if ((license.expiryDate() + GRACE_PERIOD_DURATION.getMillis()) > time) {
|
||||
return LicenseState.GRACE_PERIOD;
|
||||
}
|
||||
return LicenseState.DISABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies registered licensees of license state change and/or new active license
|
||||
* based on the license in <code>currentLicensesMetaData</code>.
|
||||
@ -508,58 +460,49 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
// license can be null if the trial license is yet to be auto-generated
|
||||
// in this case, it is a no-op
|
||||
if (license != null) {
|
||||
notifyLicensees(license);
|
||||
if (license.equals(currentLicense.get()) == false) {
|
||||
final License previousLicense = currentLicense.get();
|
||||
if (license.equals(previousLicense) == false) {
|
||||
currentLicense.set(license);
|
||||
license.setOperationModeFileWatcher(operationModeFileWatcher);
|
||||
scheduler.add(new SchedulerEngine.Job(LICENSE_JOB, new LicenseSchedule(license)));
|
||||
for (ExpirationCallback expirationCallback : expirationCallbacks) {
|
||||
scheduler.add(new SchedulerEngine.Job(expirationCallback.getId(),
|
||||
(startTime, now) ->
|
||||
expirationCallback.nextScheduledTimeForExpiry(license.expiryDate(), startTime, now)));
|
||||
}
|
||||
if (previousLicense != null) {
|
||||
// remove operationModeFileWatcher to gc the old license object
|
||||
previousLicense.removeOperationModeFileWatcher();
|
||||
}
|
||||
}
|
||||
notifyLicensees(license);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Licensee licensee) {
|
||||
for (final InternalLicensee existingLicensee : registeredLicensees) {
|
||||
if (existingLicensee.id().equals(licensee.id())) {
|
||||
throw new IllegalStateException("listener: [" + licensee.id() + "] has been already registered");
|
||||
}
|
||||
}
|
||||
logger.debug("registering licensee [{}]", licensee.id());
|
||||
registeredLicensees.add(new InternalLicensee(licensee));
|
||||
private void initLicensee(Licensee licensee) {
|
||||
logger.debug("initializing licensee [{}]", licensee.id());
|
||||
final ClusterState clusterState = clusterService.state();
|
||||
if (clusterService.lifecycleState() == Lifecycle.State.STARTED
|
||||
&& clusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK) == false
|
||||
&& clusterState.nodes().getMasterNode() != null) {
|
||||
final LicensesMetaData currentMetaData = clusterState.metaData().custom(LicensesMetaData.TYPE);
|
||||
if (currentMetaData == null || currentMetaData.getLicense() == null) {
|
||||
if (clusterState.getNodes().isLocalNodeElectedMaster() &&
|
||||
(currentMetaData == null || currentMetaData.getLicense() == null)) {
|
||||
// triggers a cluster changed event
|
||||
// eventually notifying the current licensee
|
||||
requestTrialLicense(clusterState);
|
||||
} else if (lifecycleState() == Lifecycle.State.STARTED) {
|
||||
registerTrialLicense();
|
||||
} else {
|
||||
notifyLicensees(currentMetaData.getLicense());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void requestTrialLicense(final ClusterState currentState) {
|
||||
DiscoveryNode masterNode = currentState.nodes().getMasterNode();
|
||||
if (masterNode == null) {
|
||||
throw new IllegalStateException("master not available when registering auto-generated license");
|
||||
}
|
||||
transportService.sendRequest(masterNode,
|
||||
REGISTER_TRIAL_LICENSE_ACTION_NAME, TransportRequest.Empty.INSTANCE, EmptyTransportResponseHandler.INSTANCE_SAME);
|
||||
}
|
||||
|
||||
License getLicense(final LicensesMetaData metaData) {
|
||||
if (metaData != null) {
|
||||
License license = metaData.getLicense();
|
||||
if (license == LicensesMetaData.LICENSE_TOMBSTONE) {
|
||||
return license;
|
||||
} else {
|
||||
} else if (license != null) {
|
||||
boolean autoGeneratedLicense = License.isAutoGeneratedLicense(license.signature());
|
||||
if ((autoGeneratedLicense && TrialLicense.verify(license))
|
||||
|| (!autoGeneratedLicense && LicenseVerifier.verifyLicense(license))) {
|
||||
@ -574,9 +517,9 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
* Stores acknowledgement, expiration and license notification callbacks
|
||||
* for a registered listener
|
||||
*/
|
||||
private class InternalLicensee {
|
||||
volatile License currentLicense = null;
|
||||
volatile LicenseState currentLicenseState = LicenseState.DISABLED;
|
||||
private final class InternalLicensee {
|
||||
volatile Licensee.Status currentStatus = Licensee.Status.MISSING;
|
||||
|
||||
private final Licensee licensee;
|
||||
|
||||
private InternalLicensee(Licensee licensee) {
|
||||
@ -585,7 +528,7 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(listener: " + licensee.id() + ", state: " + currentLicenseState.name() + ")";
|
||||
return "(listener: " + licensee.id() + ", state: " + currentStatus + ")";
|
||||
}
|
||||
|
||||
public String id() {
|
||||
@ -596,43 +539,21 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
||||
return licensee.expirationMessages();
|
||||
}
|
||||
|
||||
public String[] acknowledgmentMessages(License currentLicense, License newLicense) {
|
||||
return licensee.acknowledgmentMessages(currentLicense, newLicense);
|
||||
public String[] acknowledgmentMessages(License.OperationMode currentMode, License.OperationMode newMode) {
|
||||
return licensee.acknowledgmentMessages(currentMode, newMode);
|
||||
}
|
||||
|
||||
public void onChange(License license, LicenseState state) {
|
||||
synchronized (this) {
|
||||
if (currentLicense == null // not yet initialized
|
||||
|| !currentLicense.equals(license) // current license has changed
|
||||
|| currentLicenseState != state) { // same license but state has changed
|
||||
logger.debug("licensee [{}] notified", licensee.id());
|
||||
licensee.onChange(new Licensee.Status(license.operationMode(), state));
|
||||
currentLicense = license;
|
||||
currentLicenseState = state;
|
||||
}
|
||||
public synchronized void onChange(final Licensee.Status status) {
|
||||
if (currentStatus == null // not yet initialized
|
||||
|| !currentStatus.equals(status)) { // current license has changed
|
||||
logger.debug("licensee [{}] notified", licensee.id());
|
||||
licensee.onChange(status);
|
||||
currentStatus = status;
|
||||
}
|
||||
}
|
||||
|
||||
public void onRemove() {
|
||||
synchronized (this) {
|
||||
if (currentLicense != null || currentLicenseState != LicenseState.DISABLED) {
|
||||
currentLicense = null;
|
||||
currentLicenseState = LicenseState.DISABLED;
|
||||
licensee.onChange(Licensee.Status.MISSING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request handler for trial license generation to master
|
||||
*/
|
||||
private class RegisterTrialLicenseRequestHandler implements TransportRequestHandler<TransportRequest.Empty> {
|
||||
|
||||
@Override
|
||||
public void messageReceived(TransportRequest.Empty empty, TransportChannel channel) throws Exception {
|
||||
registerTrialLicense();
|
||||
channel.sendResponse(TransportResponse.Empty.INSTANCE);
|
||||
onChange(Licensee.Status.MISSING);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,29 +5,39 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.rest;
|
||||
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.action.support.AcknowledgedRestListener;
|
||||
import org.elasticsearch.xpack.XPackClient;
|
||||
import org.elasticsearch.xpack.rest.XPackRestHandler;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.DELETE;
|
||||
|
||||
public class RestDeleteLicenseAction extends BaseRestHandler {
|
||||
public class RestDeleteLicenseAction extends XPackRestHandler {
|
||||
|
||||
@Inject
|
||||
public RestDeleteLicenseAction(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
controller.registerHandler(DELETE, "/_xpack/license", this);
|
||||
// @deprecated Remove deprecations in 6.0
|
||||
controller.registerWithDeprecatedHandler(DELETE, URI_BASE + "/license", this,
|
||||
DELETE, "/_license", deprecationLogger);
|
||||
|
||||
// Remove _licenses support entirely in 6.0
|
||||
controller.registerAsDeprecatedHandler(DELETE, "/_licenses", this,
|
||||
"[DELETE /_licenses] is deprecated! Use " +
|
||||
"[DELETE /_xpack/license] instead.",
|
||||
deprecationLogger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final NodeClient client) {
|
||||
client.admin().cluster().execute(DeleteLicenseAction.INSTANCE, new DeleteLicenseRequest(), new AcknowledgedRestListener<>(channel));
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final XPackClient client) {
|
||||
client.es().admin().cluster().execute(DeleteLicenseAction.INSTANCE,
|
||||
new DeleteLicenseRequest(),
|
||||
new AcknowledgedRestListener<>(channel));
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.rest;
|
||||
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
@ -14,13 +13,14 @@ import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseResponse;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||
import org.elasticsearch.xpack.XPackClient;
|
||||
import org.elasticsearch.xpack.rest.XPackRestHandler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -29,12 +29,20 @@ import static org.elasticsearch.rest.RestRequest.Method.GET;
|
||||
import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
|
||||
import static org.elasticsearch.rest.RestStatus.OK;
|
||||
|
||||
public class RestGetLicenseAction extends BaseRestHandler {
|
||||
public class RestGetLicenseAction extends XPackRestHandler {
|
||||
|
||||
@Inject
|
||||
public RestGetLicenseAction(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
controller.registerHandler(GET, "/_xpack/license", this);
|
||||
// @deprecated Remove deprecations in 6.0
|
||||
controller.registerWithDeprecatedHandler(GET, URI_BASE + "/license", this,
|
||||
GET, "/_license", deprecationLogger);
|
||||
|
||||
// Remove _licenses support entirely in 6.0
|
||||
controller.registerAsDeprecatedHandler(GET, "/_licenses", this,
|
||||
"[GET /_licenses] is deprecated! Use " +
|
||||
"[GET /_xpack/license] instead.",
|
||||
deprecationLogger);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,14 +52,14 @@ public class RestGetLicenseAction extends BaseRestHandler {
|
||||
* The licenses are sorted by latest issue_date
|
||||
*/
|
||||
@Override
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final NodeClient client) {
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final XPackClient client) {
|
||||
final Map<String, String> overrideParams = new HashMap<>(2);
|
||||
overrideParams.put(License.REST_VIEW_MODE, "true");
|
||||
overrideParams.put(License.LICENSE_VERSION_MODE, String.valueOf(License.VERSION_CURRENT));
|
||||
final ToXContent.Params params = new ToXContent.DelegatingMapParams(overrideParams, request);
|
||||
GetLicenseRequest getLicenseRequest = new GetLicenseRequest();
|
||||
getLicenseRequest.local(request.paramAsBoolean("local", getLicenseRequest.local()));
|
||||
client.admin().cluster().execute(GetLicenseAction.INSTANCE, getLicenseRequest,
|
||||
client.es().admin().cluster().execute(GetLicenseAction.INSTANCE, getLicenseRequest,
|
||||
new RestBuilderListener<GetLicenseResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(GetLicenseResponse response, XContentBuilder builder) throws Exception {
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.rest;
|
||||
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
@ -13,7 +12,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
@ -21,25 +19,40 @@ import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||
import org.elasticsearch.xpack.XPackClient;
|
||||
import org.elasticsearch.xpack.rest.XPackRestHandler;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
||||
|
||||
public class RestPutLicenseAction extends BaseRestHandler {
|
||||
public class RestPutLicenseAction extends XPackRestHandler {
|
||||
|
||||
@Inject
|
||||
public RestPutLicenseAction(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
controller.registerHandler(PUT, "/_xpack/license", this);
|
||||
controller.registerHandler(POST, "/_xpack/license", this);
|
||||
// @deprecated Remove deprecations in 6.0
|
||||
controller.registerWithDeprecatedHandler(POST, URI_BASE + "/license", this,
|
||||
POST, "/_license", deprecationLogger);
|
||||
controller.registerWithDeprecatedHandler(PUT, URI_BASE + "/license", this,
|
||||
PUT, "/_license", deprecationLogger);
|
||||
|
||||
// Remove _licenses support entirely in 6.0
|
||||
controller.registerAsDeprecatedHandler(POST, "/_licenses", this,
|
||||
"[POST /_licenses] is deprecated! Use " +
|
||||
"[POST /_xpack/license] instead.",
|
||||
deprecationLogger);
|
||||
controller.registerAsDeprecatedHandler(PUT, "/_licenses", this,
|
||||
"[PUT /_licenses] is deprecated! Use " +
|
||||
"[PUT /_xpack/license] instead.",
|
||||
deprecationLogger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final NodeClient client) {
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final XPackClient client) {
|
||||
PutLicenseRequest putLicenseRequest = new PutLicenseRequest();
|
||||
putLicenseRequest.license(request.content().utf8ToString());
|
||||
putLicenseRequest.acknowledge(request.paramAsBoolean("acknowledge", false));
|
||||
client.admin().cluster().execute(PutLicenseAction.INSTANCE, putLicenseRequest,
|
||||
client.es().admin().cluster().execute(PutLicenseAction.INSTANCE, putLicenseRequest,
|
||||
new RestBuilderListener<PutLicenseResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(PutLicenseResponse response, XContentBuilder builder) throws Exception {
|
||||
|
@ -5,36 +5,27 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin;
|
||||
|
||||
import org.elasticsearch.client.ClusterAdminClient;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequestBuilder;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseRequestBuilder;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.LicensesMetaData;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesStatus;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.xpack.MockNetty3Plugin;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense;
|
||||
import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
|
||||
@ClusterScope(scope = TEST, numDataNodes = 0, numClientNodes = 0, maxNumDataNodes = 0, transportClientRatio = 0)
|
||||
@ -54,12 +45,13 @@ public class LicensesServiceClusterTests extends AbstractLicensesIntegrationTest
|
||||
return Settings.builder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put("node.data", true)
|
||||
.put("resource.reload.interval.high", "500ms") // for license mode file watcher
|
||||
.put(NetworkModule.HTTP_ENABLED.getKey(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
||||
return Collections.singletonList(XPackPlugin.class);
|
||||
return Arrays.asList(XPackPlugin.class, MockNetty3Plugin.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -78,37 +70,54 @@ public class LicensesServiceClusterTests extends AbstractLicensesIntegrationTest
|
||||
ensureGreen();
|
||||
|
||||
logger.info("--> put signed license");
|
||||
License license = generateAndPutLicenses();
|
||||
getAndCheckLicense(license);
|
||||
LicensingClient licensingClient = new LicensingClient(client());
|
||||
License license = generateSignedLicense(TimeValue.timeValueMinutes(1));
|
||||
putLicense(license);
|
||||
assertThat(licensingClient.prepareGetLicense().get().license(), equalTo(license));
|
||||
assertOperationMode(license.operationMode());
|
||||
|
||||
logger.info("--> restart all nodes");
|
||||
internalCluster().fullRestart();
|
||||
ensureYellow();
|
||||
|
||||
licensingClient = new LicensingClient(client());
|
||||
logger.info("--> get and check signed license");
|
||||
getAndCheckLicense(license);
|
||||
|
||||
assertThat(licensingClient.prepareGetLicense().get().license(), equalTo(license));
|
||||
logger.info("--> remove licenses");
|
||||
removeLicense();
|
||||
assertNoLicense();
|
||||
licensingClient.prepareDeleteLicense().get();
|
||||
assertOperationMode(License.OperationMode.MISSING);
|
||||
|
||||
logger.info("--> restart all nodes");
|
||||
internalCluster().fullRestart();
|
||||
licensingClient = new LicensingClient(client());
|
||||
ensureYellow();
|
||||
assertNoLicense();
|
||||
assertThat(licensingClient.prepareGetLicense().get().license(), nullValue());
|
||||
assertOperationMode(License.OperationMode.MISSING);
|
||||
|
||||
|
||||
wipeAllLicenses();
|
||||
}
|
||||
|
||||
public void testCloudInternalLicense() throws Exception {
|
||||
wipeAllLicenses();
|
||||
|
||||
private void assertLicenseState(LicenseState state) throws InterruptedException {
|
||||
boolean success = awaitBusy(() -> {
|
||||
for (LicensesService service : internalCluster().getDataNodeInstances(LicensesService.class)) {
|
||||
if (service.licenseState() == state) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
assertTrue(success);
|
||||
int numNodes = randomIntBetween(1, 5);
|
||||
logger.info("--> starting {} node(s)", numNodes);
|
||||
for (int i = 0; i < numNodes; i++) {
|
||||
internalCluster().startNode();
|
||||
}
|
||||
ensureGreen();
|
||||
|
||||
logger.info("--> put signed license");
|
||||
LicensingClient licensingClient = new LicensingClient(client());
|
||||
License license = generateSignedLicense("cloud_internal", License.VERSION_CURRENT, System.currentTimeMillis(),
|
||||
TimeValue.timeValueMinutes(1));
|
||||
putLicense(license);
|
||||
assertThat(licensingClient.prepareGetLicense().get().license(), equalTo(license));
|
||||
assertOperationMode(License.OperationMode.PLATINUM);
|
||||
writeCloudInternalMode("gold");
|
||||
assertOperationMode(License.OperationMode.GOLD);
|
||||
writeCloudInternalMode("basic");
|
||||
assertOperationMode(License.OperationMode.BASIC);
|
||||
}
|
||||
|
||||
public void testClusterRestartWhileEnabled() throws Exception {
|
||||
@ -142,7 +151,7 @@ public class LicensesServiceClusterTests extends AbstractLicensesIntegrationTest
|
||||
internalCluster().startNode();
|
||||
ensureGreen();
|
||||
assertLicenseState(LicenseState.ENABLED);
|
||||
putLicense(TestUtils.generateExpiredLicense(System.currentTimeMillis() - LicensesService.GRACE_PERIOD_DURATION.getMillis()));
|
||||
putLicense(TestUtils.generateExpiredLicense(System.currentTimeMillis() - LicenseState.GRACE_PERIOD_DURATION.getMillis()));
|
||||
assertLicenseState(LicenseState.DISABLED);
|
||||
logger.info("--> restart node");
|
||||
internalCluster().fullRestart();
|
||||
@ -159,43 +168,36 @@ public class LicensesServiceClusterTests extends AbstractLicensesIntegrationTest
|
||||
assertLicenseState(LicenseState.ENABLED);
|
||||
}
|
||||
|
||||
private void removeLicense() throws Exception {
|
||||
ClusterAdminClient cluster = internalCluster().client().admin().cluster();
|
||||
ensureGreen();
|
||||
License putLicenses = generateSignedLicense(TimeValue.timeValueMinutes(1));
|
||||
PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(cluster, PutLicenseAction.INSTANCE);
|
||||
putLicenseRequestBuilder.setLicense(putLicenses);
|
||||
DeleteLicenseResponse response = new DeleteLicenseRequestBuilder(cluster, DeleteLicenseAction.INSTANCE).get();
|
||||
assertThat(response.isAcknowledged(), equalTo(true));
|
||||
private void assertLicenseState(LicenseState state) throws InterruptedException {
|
||||
boolean success = awaitBusy(() -> {
|
||||
for (LicensesService service : internalCluster().getDataNodeInstances(LicensesService.class)) {
|
||||
if (service.licenseeStatus().getLicenseState() == state) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
assertTrue(success);
|
||||
}
|
||||
|
||||
private License generateAndPutLicenses() throws Exception {
|
||||
ClusterAdminClient cluster = internalCluster().client().admin().cluster();
|
||||
ensureGreen();
|
||||
License putLicenses = generateSignedLicense(TimeValue.timeValueMinutes(1));
|
||||
PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(cluster, PutLicenseAction.INSTANCE);
|
||||
putLicenseRequestBuilder.setLicense(putLicenses);
|
||||
final PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get();
|
||||
assertThat(putLicenseResponse.isAcknowledged(), equalTo(true));
|
||||
assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID));
|
||||
return putLicenses;
|
||||
private void assertOperationMode(License.OperationMode operationMode) throws InterruptedException {
|
||||
boolean success = awaitBusy(() -> {
|
||||
for (LicensesService service : internalCluster().getDataNodeInstances(LicensesService.class)) {
|
||||
if (service.licenseeStatus().getMode() == operationMode) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
assertTrue(success);
|
||||
}
|
||||
|
||||
private void assertNoLicense() {
|
||||
ClusterAdminClient cluster = internalCluster().client().admin().cluster();
|
||||
final GetLicenseResponse response = new GetLicenseRequestBuilder(cluster, GetLicenseAction.INSTANCE).get();
|
||||
assertThat(response.license(), nullValue());
|
||||
LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE);
|
||||
assertThat(licensesMetaData, notNullValue());
|
||||
assertThat(licensesMetaData.getLicense(), equalTo(LicensesMetaData.LICENSE_TOMBSTONE));
|
||||
private void writeCloudInternalMode(String mode) throws Exception {
|
||||
for (Environment environment : internalCluster().getDataOrMasterNodeInstances(Environment.class)) {
|
||||
Path licenseModePath = XPackPlugin.resolveConfigFile(environment, "license_mode");
|
||||
Files.createDirectories(licenseModePath.getParent());
|
||||
Files.write(licenseModePath, mode.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
private void getAndCheckLicense(License license) {
|
||||
ClusterAdminClient cluster = internalCluster().client().admin().cluster();
|
||||
final GetLicenseResponse response = new GetLicenseRequestBuilder(cluster, GetLicenseAction.INSTANCE).get();
|
||||
assertThat(response.license(), equalTo(license));
|
||||
LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE);
|
||||
assertThat(licensesMetaData, notNullValue());
|
||||
assertThat(licensesMetaData.getLicense(), not(LicensesMetaData.LICENSE_TOMBSTONE));
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,6 @@
|
||||
package org.elasticsearch.license.plugin;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.block.ClusterBlock;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.io.PathUtils;
|
||||
import org.elasticsearch.common.joda.DateMathParser;
|
||||
@ -29,10 +26,8 @@ import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesStatus;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
@ -92,8 +87,11 @@ public class TestUtils {
|
||||
}
|
||||
|
||||
public static License generateSignedLicense(String type, long issueDate, TimeValue expiryDuration) throws Exception {
|
||||
return generateSignedLicense(type, randomIntBetween(License.VERSION_START, License.VERSION_CURRENT), issueDate, expiryDuration);
|
||||
}
|
||||
|
||||
public static License generateSignedLicense(String type, int version, long issueDate, TimeValue expiryDuration) throws Exception {
|
||||
long issue = (issueDate != -1L) ? issueDate : System.currentTimeMillis() - TimeValue.timeValueHours(2).getMillis();
|
||||
int version = randomIntBetween(License.VERSION_START, License.VERSION_CURRENT);
|
||||
final String licenseType;
|
||||
if (version < License.VERSION_NO_FEATURE_TYPE) {
|
||||
licenseType = randomFrom("subscription", "internal", "development");
|
||||
@ -117,17 +115,26 @@ public class TestUtils {
|
||||
return signer.sign(builder.build());
|
||||
}
|
||||
|
||||
public static License generateExpiredLicense() throws Exception {
|
||||
return generateExpiredLicense(System.currentTimeMillis() - TimeValue.timeValueHours(randomIntBetween(1, 10)).getMillis());
|
||||
public static License generateExpiredLicense(long expiryDate) throws Exception {
|
||||
return generateExpiredLicense(randomFrom("basic", "silver", "dev", "gold", "platinum"), expiryDate);
|
||||
}
|
||||
|
||||
public static License generateExpiredLicense(long expiryDate) throws Exception {
|
||||
public static License generateExpiredLicense() throws Exception {
|
||||
return generateExpiredLicense(randomFrom("basic", "silver", "dev", "gold", "platinum"));
|
||||
}
|
||||
|
||||
public static License generateExpiredLicense(String type) throws Exception {
|
||||
return generateExpiredLicense(type,
|
||||
System.currentTimeMillis() - TimeValue.timeValueHours(randomIntBetween(1, 10)).getMillis());
|
||||
}
|
||||
|
||||
public static License generateExpiredLicense(String type, long expiryDate) throws Exception {
|
||||
final License.Builder builder = License.builder()
|
||||
.uid(UUID.randomUUID().toString())
|
||||
.version(License.VERSION_CURRENT)
|
||||
.expiryDate(expiryDate)
|
||||
.issueDate(expiryDate - TimeValue.timeValueMinutes(10).getMillis())
|
||||
.type(randomFrom("basic", "silver", "dev", "gold", "platinum"))
|
||||
.type(type)
|
||||
.issuedTo("customer")
|
||||
.issuer("elasticsearch")
|
||||
.maxNodes(5);
|
||||
@ -139,23 +146,9 @@ public class TestUtils {
|
||||
return PathUtils.get(TestUtils.class.getResource(resource).toURI());
|
||||
}
|
||||
|
||||
public static void awaitNoBlock(final Client client) throws InterruptedException {
|
||||
boolean success = awaitBusy(() -> {
|
||||
Set<ClusterBlock> clusterBlocks = client.admin().cluster().prepareState().setLocal(true).execute().actionGet()
|
||||
.getState().blocks().global(ClusterBlockLevel.METADATA_WRITE);
|
||||
return clusterBlocks.isEmpty();
|
||||
});
|
||||
assertThat("awaiting no block for too long", success, equalTo(true));
|
||||
}
|
||||
|
||||
public static void awaitNoPendingTasks(final Client client) throws InterruptedException {
|
||||
boolean success = awaitBusy(() -> client.admin().cluster().preparePendingClusterTasks().get().getPendingTasks().isEmpty());
|
||||
assertThat("awaiting no pending tasks for too long", success, equalTo(true));
|
||||
}
|
||||
|
||||
public static void registerAndAckSignedLicenses(final LicensesService licensesService, License license,
|
||||
final LicensesStatus expectedStatus) {
|
||||
PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(license);
|
||||
PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(license).acknowledge(true);
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
final AtomicReference<LicensesStatus> status = new AtomicReference<>();
|
||||
licensesService.registerLicense(putLicenseRequest, new ActionListener<PutLicenseResponse>() {
|
||||
@ -183,7 +176,7 @@ public class TestUtils {
|
||||
public final String id;
|
||||
public final List<Licensee.Status> statuses = new CopyOnWriteArrayList<>();
|
||||
public final AtomicInteger expirationMessagesCalled = new AtomicInteger(0);
|
||||
public final List<Tuple<License, License>> acknowledgementRequested = new CopyOnWriteArrayList<>();
|
||||
public final List<Tuple<License.OperationMode, License.OperationMode>> acknowledgementRequested = new CopyOnWriteArrayList<>();
|
||||
|
||||
private String[] acknowledgmentMessages = new String[0];
|
||||
|
||||
@ -207,8 +200,8 @@ public class TestUtils {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] acknowledgmentMessages(License currentLicense, License newLicense) {
|
||||
acknowledgementRequested.add(new Tuple<>(currentLicense, newLicense));
|
||||
public String[] acknowledgmentMessages(License.OperationMode currentMode, License.OperationMode newMode) {
|
||||
acknowledgementRequested.add(new Tuple<>(currentMode, newMode));
|
||||
return acknowledgmentMessages;
|
||||
}
|
||||
|
||||
@ -218,4 +211,4 @@ public class TestUtils {
|
||||
statuses.add(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,10 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.core;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.block.ClusterBlocks;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
@ -15,13 +18,16 @@ import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.component.Lifecycle;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.LocalTransportAddress;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
import org.elasticsearch.xpack.scheduler.SchedulerEngine;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.support.clock.ClockMock;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@ -31,29 +37,43 @@ public abstract class AbstractLicenseServiceTestCase extends ESTestCase {
|
||||
|
||||
protected LicensesService licensesService;
|
||||
protected ClusterService clusterService;
|
||||
protected TransportService transportService;
|
||||
protected ResourceWatcherService resourceWatcherService;
|
||||
protected ClockMock clock;
|
||||
protected DiscoveryNodes discoveryNodes;
|
||||
protected Environment environment;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
clusterService = mock(ClusterService.class);
|
||||
transportService = mock(TransportService.class);
|
||||
clock = new ClockMock();
|
||||
licensesService = new LicensesService(Settings.EMPTY, clusterService, transportService, clock);
|
||||
discoveryNodes = mock(DiscoveryNodes.class);
|
||||
resourceWatcherService = mock(ResourceWatcherService.class);
|
||||
environment = mock(Environment.class);
|
||||
}
|
||||
|
||||
protected void setInitialState(License license) {
|
||||
protected void setInitialState(License license, Licensee... licensees) {
|
||||
Path tempDir = createTempDir();
|
||||
when(environment.configFile()).thenReturn(tempDir);
|
||||
licensesService = new LicensesService(Settings.EMPTY, clusterService, clock, environment,
|
||||
resourceWatcherService, Arrays.asList(licensees));
|
||||
ClusterState state = mock(ClusterState.class);
|
||||
final ClusterBlocks noBlock = ClusterBlocks.builder().build();
|
||||
when(state.blocks()).thenReturn(noBlock);
|
||||
MetaData metaData = mock(MetaData.class);
|
||||
when(metaData.custom(LicensesMetaData.TYPE)).thenReturn(new LicensesMetaData(license));
|
||||
when(state.metaData()).thenReturn(metaData);
|
||||
final DiscoveryNodes discoveryNodes = mock(DiscoveryNodes.class);
|
||||
final DiscoveryNode mockNode = new DiscoveryNode("b", LocalTransportAddress.buildUnique(), emptyMap(), emptySet(), Version.CURRENT);
|
||||
when(discoveryNodes.getMasterNode()).thenReturn(mockNode);
|
||||
when(discoveryNodes.isLocalNodeElectedMaster()).thenReturn(false);
|
||||
when(state.nodes()).thenReturn(discoveryNodes);
|
||||
when(state.getNodes()).thenReturn(discoveryNodes); // it is really ridiculous we have nodes() and getNodes()...
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
when(clusterService.lifecycleState()).thenReturn(Lifecycle.State.STARTED);
|
||||
when(clusterService.getClusterName()).thenReturn(new ClusterName("a"));
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
licensesService.stop();
|
||||
}
|
||||
}
|
||||
|
@ -39,17 +39,8 @@ public abstract class AbstractLicenseeTestCase extends ESTestCase {
|
||||
* @param licensee The licensee to test
|
||||
*/
|
||||
public static void assertEmptyAck(OperationMode fromMode, OperationMode toMode, Licensee licensee) {
|
||||
License fromLicense = mock(License.class);
|
||||
when(fromLicense.operationMode()).thenReturn(fromMode);
|
||||
License toLicense = mock(License.class);
|
||||
when(toLicense.operationMode()).thenReturn(toMode);
|
||||
|
||||
if (randomBoolean()) {
|
||||
fromLicense = null;
|
||||
}
|
||||
|
||||
// test it
|
||||
String[] messages = licensee.acknowledgmentMessages(fromLicense, toLicense);
|
||||
String[] messages = licensee.acknowledgmentMessages(fromMode, toMode);
|
||||
|
||||
assertThat(fromToMessage(fromMode, toMode), messages.length, equalTo(0));
|
||||
}
|
||||
@ -77,12 +68,7 @@ public abstract class AbstractLicenseeTestCase extends ESTestCase {
|
||||
* @param licensee The licensee to test
|
||||
*/
|
||||
public static String[] ackLicenseChange(OperationMode fromMode, OperationMode toMode, Licensee licensee) {
|
||||
License fromLicense = mock(License.class);
|
||||
when(fromLicense.operationMode()).thenReturn(fromMode);
|
||||
License toLicense = mock(License.class);
|
||||
when(toLicense.operationMode()).thenReturn(toMode);
|
||||
|
||||
return licensee.acknowledgmentMessages(fromLicense, toLicense);
|
||||
return licensee.acknowledgmentMessages(fromMode, toMode);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,35 +155,18 @@ public abstract class AbstractLicenseeTestCase extends ESTestCase {
|
||||
return String.format(Locale.ROOT, "From [%s] to [%s]", fromMode, toMode);
|
||||
}
|
||||
|
||||
public static class SimpleLicenseeRegistry extends AbstractComponent implements LicenseeRegistry {
|
||||
private final List<Licensee> licensees = new ArrayList<>();
|
||||
private OperationMode operationMode;
|
||||
private OperationMode operationMode;
|
||||
|
||||
public SimpleLicenseeRegistry() {
|
||||
super(Settings.EMPTY);
|
||||
}
|
||||
public void setOperationMode(Licensee licensee, OperationMode operationMode) {
|
||||
this.operationMode = operationMode;
|
||||
enable(licensee);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Licensee licensee) {
|
||||
licensees.add(licensee);
|
||||
enable();
|
||||
}
|
||||
public void disable(Licensee licensee) {
|
||||
licensee.onChange(new Licensee.Status(operationMode, LicenseState.DISABLED));
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
for (Licensee licensee : licensees) {
|
||||
licensee.onChange(new Licensee.Status(operationMode, randomEnabledOrGracePeriodState()));
|
||||
}
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
for (Licensee licensee : licensees) {
|
||||
licensee.onChange(new Licensee.Status(operationMode, LicenseState.DISABLED));
|
||||
}
|
||||
}
|
||||
|
||||
public void setOperationMode(License.OperationMode operationMode) {
|
||||
this.operationMode = operationMode;
|
||||
enable();
|
||||
}
|
||||
public void enable(Licensee licensee) {
|
||||
licensee.onChange(new Licensee.Status(operationMode, randomEnabledOrGracePeriodState()));
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cluster.ClusterChangedEvent;
|
||||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
||||
@ -16,18 +17,17 @@ import org.elasticsearch.common.transport.LocalTransportAddress;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.TestUtils;
|
||||
import org.elasticsearch.transport.EmptyTransportResponseHandler;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class LicenseClusterChangeTests extends AbstractLicenseServiceTestCase {
|
||||
|
||||
@ -35,10 +35,9 @@ public class LicenseClusterChangeTests extends AbstractLicenseServiceTestCase {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
setInitialState(null);
|
||||
licensesService.start();
|
||||
licensee = new TestUtils.AssertingLicensee("LicenseClusterChangeTests", logger);
|
||||
licensesService.register(licensee);
|
||||
setInitialState(null, licensee);
|
||||
licensesService.start();
|
||||
}
|
||||
|
||||
@After
|
||||
@ -70,11 +69,16 @@ public class LicenseClusterChangeTests extends AbstractLicenseServiceTestCase {
|
||||
DiscoveryNode master = new DiscoveryNode("b", LocalTransportAddress.buildUnique(), emptyMap(), emptySet(), Version.CURRENT);
|
||||
ClusterState oldState = ClusterState.builder(new ClusterName("a"))
|
||||
.nodes(DiscoveryNodes.builder().masterNodeId(master.getId()).put(master)).build();
|
||||
ClusterState newState = ClusterState.builder(oldState).build();
|
||||
when(discoveryNodes.isLocalNodeElectedMaster()).thenReturn(true);
|
||||
ClusterState newState = ClusterState.builder(oldState).nodes(discoveryNodes).build();
|
||||
|
||||
licensesService.clusterChanged(new ClusterChangedEvent("simulated", newState, oldState));
|
||||
verify(transportService, times(2))
|
||||
.sendRequest(any(DiscoveryNode.class),
|
||||
eq(LicensesService.REGISTER_TRIAL_LICENSE_ACTION_NAME),
|
||||
any(TransportRequest.Empty.class), any(EmptyTransportResponseHandler.class));
|
||||
ArgumentCaptor<ClusterStateUpdateTask> stateUpdater = ArgumentCaptor.forClass(ClusterStateUpdateTask.class);
|
||||
verify(clusterService, times(1)).submitStateUpdateTask(any(), stateUpdater.capture());
|
||||
ClusterState stateWithLicense = stateUpdater.getValue().execute(newState);
|
||||
LicensesMetaData licenseMetaData = stateWithLicense.metaData().custom(LicensesMetaData.TYPE);
|
||||
assertNotNull(licenseMetaData);
|
||||
assertNotNull(licenseMetaData.getLicense());
|
||||
assertEquals(clock.millis() + LicensesService.TRIAL_LICENSE_DURATION.millis(), licenseMetaData.getLicense().expiryDate());
|
||||
}
|
||||
}
|
@ -5,43 +5,45 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.core;
|
||||
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.license.plugin.TestUtils;
|
||||
import org.elasticsearch.transport.EmptyTransportResponseHandler;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import static org.elasticsearch.mock.orig.Mockito.times;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class LicenseRegistrationTests extends AbstractLicenseServiceTestCase {
|
||||
|
||||
public void testTrialLicenseRequestOnEmptyLicenseState() throws Exception {
|
||||
setInitialState(null);
|
||||
TestUtils.AssertingLicensee licensee = new TestUtils.AssertingLicensee(
|
||||
"testTrialLicenseRequestOnEmptyLicenseState", logger);
|
||||
"testTrialLicenseRequestOnEmptyLicenseState", logger);
|
||||
setInitialState(null, licensee);
|
||||
when(discoveryNodes.isLocalNodeElectedMaster()).thenReturn(true);
|
||||
licensesService.start();
|
||||
licensesService.register(licensee);
|
||||
verify(transportService, times(1))
|
||||
.sendRequest(any(DiscoveryNode.class),
|
||||
eq(LicensesService.REGISTER_TRIAL_LICENSE_ACTION_NAME),
|
||||
any(TransportRequest.Empty.class), any(EmptyTransportResponseHandler.class));
|
||||
assertThat(licensee.statuses.size(), equalTo(0));
|
||||
licensesService.stop();
|
||||
|
||||
ClusterState state = ClusterState.builder(new ClusterName("a")).build();
|
||||
ArgumentCaptor<ClusterStateUpdateTask> stateUpdater = ArgumentCaptor.forClass(ClusterStateUpdateTask.class);
|
||||
verify(clusterService, Mockito.times(1)).submitStateUpdateTask(any(), stateUpdater.capture());
|
||||
ClusterState stateWithLicense = stateUpdater.getValue().execute(state);
|
||||
LicensesMetaData licenseMetaData = stateWithLicense.metaData().custom(LicensesMetaData.TYPE);
|
||||
assertNotNull(licenseMetaData);
|
||||
assertNotNull(licenseMetaData.getLicense());
|
||||
assertEquals(clock.millis() + LicensesService.TRIAL_LICENSE_DURATION.millis(), licenseMetaData.getLicense().expiryDate());
|
||||
}
|
||||
|
||||
public void testNotificationOnRegistration() throws Exception {
|
||||
setInitialState(TestUtils.generateSignedLicense(TimeValue.timeValueHours(2)));
|
||||
TestUtils.AssertingLicensee licensee = new TestUtils.AssertingLicensee(
|
||||
"testNotificationOnRegistration", logger);
|
||||
setInitialState(TestUtils.generateSignedLicense(TimeValue.timeValueHours(2)), licensee);
|
||||
licensesService.start();
|
||||
licensesService.register(licensee);
|
||||
assertThat(licensee.statuses.size(), equalTo(1));
|
||||
final LicenseState licenseState = licensee.statuses.get(0).getLicenseState();
|
||||
assertTrue(licenseState == LicenseState.ENABLED);
|
||||
licensesService.stop();
|
||||
}
|
||||
}
|
@ -32,13 +32,13 @@ public class LicenseScheduleTests extends ESTestCase {
|
||||
|
||||
public void testGraceLicenseSchedule() throws Exception {
|
||||
long triggeredTime = license.expiryDate() + between(1,
|
||||
((int) LicensesService.GRACE_PERIOD_DURATION.getMillis()));
|
||||
((int) LicenseState.GRACE_PERIOD_DURATION.getMillis()));
|
||||
assertThat(schedule.nextScheduledTimeAfter(license.issueDate(), triggeredTime),
|
||||
equalTo(license.expiryDate() + LicensesService.GRACE_PERIOD_DURATION.getMillis()));
|
||||
equalTo(license.expiryDate() + LicenseState.GRACE_PERIOD_DURATION.getMillis()));
|
||||
}
|
||||
|
||||
public void testExpiredLicenseSchedule() throws Exception {
|
||||
long triggeredTime = license.expiryDate() + LicensesService.GRACE_PERIOD_DURATION.getMillis() +
|
||||
long triggeredTime = license.expiryDate() + LicenseState.GRACE_PERIOD_DURATION.getMillis() +
|
||||
randomIntBetween(1, 1000);
|
||||
assertThat(schedule.nextScheduledTimeAfter(license.issueDate(), triggeredTime),
|
||||
equalTo(-1L));
|
||||
@ -49,4 +49,4 @@ public class LicenseScheduleTests extends ESTestCase {
|
||||
assertThat(schedule.nextScheduledTimeAfter(triggeredTime, triggeredTime),
|
||||
equalTo(license.issueDate()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,10 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.core;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
@ -13,10 +17,6 @@ import org.elasticsearch.license.plugin.TestUtils;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
@ -27,13 +27,13 @@ import static org.mockito.Mockito.verify;
|
||||
public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase {
|
||||
|
||||
public void testAcknowledgment() throws Exception {
|
||||
setInitialState(TestUtils.generateSignedLicense("trial", TimeValue.timeValueHours(2)));
|
||||
licensesService.start();
|
||||
|
||||
String id = "testAcknowledgment";
|
||||
String[] acknowledgeMessages = new String[] {"message"};
|
||||
TestUtils.AssertingLicensee licensee = new TestUtils.AssertingLicensee(id, logger);
|
||||
setInitialState(TestUtils.generateSignedLicense("trial", TimeValue.timeValueHours(2)), licensee);
|
||||
licensesService.start();
|
||||
licensee.setAcknowledgementMessages(acknowledgeMessages);
|
||||
licensesService.register(licensee);
|
||||
// try installing a signed license
|
||||
License signedLicense = generateSignedLicense(TimeValue.timeValueHours(10));
|
||||
PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense);
|
||||
@ -41,7 +41,7 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase
|
||||
licensesService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID,
|
||||
Collections.singletonMap(id, acknowledgeMessages)));
|
||||
assertThat(licensee.acknowledgementRequested.size(), equalTo(1));
|
||||
assertThat(licensee.acknowledgementRequested.get(0).v2(), equalTo(signedLicense));
|
||||
assertThat(licensee.acknowledgementRequested.get(0).v2(), equalTo(signedLicense.operationMode()));
|
||||
assertThat(licensesService.getLicense(), not(signedLicense));
|
||||
|
||||
// try installing a signed license with acknowledgement
|
||||
@ -52,13 +52,10 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase
|
||||
Collections.<String, String[]>emptyMap()));
|
||||
verify(clusterService, times(1)).submitStateUpdateTask(any(String.class), any(ClusterStateUpdateTask.class));
|
||||
assertThat(licensee.acknowledgementRequested.size(), equalTo(1));
|
||||
assertThat(licensee.acknowledgementRequested.get(0).v2(), equalTo(signedLicense));
|
||||
licensesService.stop();
|
||||
assertThat(licensee.acknowledgementRequested.get(0).v2(), equalTo(signedLicense.operationMode()));
|
||||
}
|
||||
|
||||
public void testAcknowledgementMultipleLicensee() throws Exception {
|
||||
setInitialState(TestUtils.generateSignedLicense("trial", TimeValue.timeValueHours(2)));
|
||||
licensesService.start();
|
||||
String id1 = "testAcknowledgementMultipleLicensee_1";
|
||||
String[] acknowledgeMessages1 = new String[] {"testAcknowledgementMultipleLicensee_1"};
|
||||
String id2 = "testAcknowledgementMultipleLicensee_2";
|
||||
@ -67,8 +64,8 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase
|
||||
licensee1.setAcknowledgementMessages(acknowledgeMessages1);
|
||||
TestUtils.AssertingLicensee licensee2 = new TestUtils.AssertingLicensee(id2, logger);
|
||||
licensee2.setAcknowledgementMessages(acknowledgeMessages2);
|
||||
licensesService.register(licensee1);
|
||||
licensesService.register(licensee2);
|
||||
setInitialState(TestUtils.generateSignedLicense("trial", TimeValue.timeValueHours(2)), licensee1, licensee2);
|
||||
licensesService.start();
|
||||
// try installing a signed license
|
||||
License signedLicense = generateSignedLicense(TimeValue.timeValueHours(10));
|
||||
PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense);
|
||||
@ -80,9 +77,9 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase
|
||||
expectedMessages));
|
||||
verify(clusterService, times(0)).submitStateUpdateTask(any(String.class), any(ClusterStateUpdateTask.class));
|
||||
assertThat(licensee2.acknowledgementRequested.size(), equalTo(1));
|
||||
assertThat(licensee2.acknowledgementRequested.get(0).v2(), equalTo(signedLicense));
|
||||
assertThat(licensee2.acknowledgementRequested.get(0).v2(), equalTo(signedLicense.operationMode()));
|
||||
assertThat(licensee1.acknowledgementRequested.size(), equalTo(1));
|
||||
assertThat(licensee1.acknowledgementRequested.get(0).v2(), equalTo(signedLicense));
|
||||
assertThat(licensee1.acknowledgementRequested.get(0).v2(), equalTo(signedLicense.operationMode()));
|
||||
assertThat(licensesService.getLicense(), not(signedLicense));
|
||||
|
||||
// try installing a signed license with acknowledgement
|
||||
@ -93,7 +90,6 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase
|
||||
licensesService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(true, LicensesStatus.VALID,
|
||||
Collections.<String, String[]>emptyMap()));
|
||||
verify(clusterService, times(1)).submitStateUpdateTask(any(String.class), any(ClusterStateUpdateTask.class));
|
||||
licensesService.stop();
|
||||
}
|
||||
|
||||
private static class AssertingLicensesUpdateResponse implements ActionListener<PutLicenseResponse> {
|
||||
@ -125,4 +121,4 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase
|
||||
public void onFailure(Exception throwable) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,27 +5,27 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.core;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.xpack.graph.Graph;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.TestUtils;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest;
|
||||
import org.elasticsearch.xpack.monitoring.Monitoring;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.test.ESSingleNodeTestCase;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.graph.Graph;
|
||||
import org.elasticsearch.xpack.monitoring.Monitoring;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.watcher.Watcher;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
@ -116,9 +116,6 @@ public class LicensesManagerServiceTests extends ESSingleNodeTestCase {
|
||||
LicensesService licensesService = getInstanceFromNode(LicensesService.class);
|
||||
ClusterService clusterService = getInstanceFromNode(ClusterService.class);
|
||||
|
||||
// generate a trial license for one feature
|
||||
licensesService.register(new TestUtils.AssertingLicensee("", logger));
|
||||
|
||||
// generate signed licenses
|
||||
License license = generateSignedLicense(TimeValue.timeValueHours(1));
|
||||
TestUtils.registerAndAckSignedLicenses(licensesService, license, LicensesStatus.VALID);
|
||||
@ -131,53 +128,6 @@ public class LicensesManagerServiceTests extends ESSingleNodeTestCase {
|
||||
assertThat(licensesMetaData.getLicense(), equalTo(LicensesMetaData.LICENSE_TOMBSTONE));
|
||||
}
|
||||
|
||||
public void testRemoveLicensesAndLicenseeNotification() throws Exception {
|
||||
LicensesService licensesService = getInstanceFromNode(LicensesService.class);
|
||||
licensesService.start();
|
||||
ClusterService clusterService = getInstanceFromNode(ClusterService.class);
|
||||
|
||||
// generate a trial license for one feature
|
||||
TestUtils.AssertingLicensee licensee = new TestUtils.AssertingLicensee("", logger);
|
||||
licensesService.register(licensee);
|
||||
|
||||
// we should get a trial license to begin with
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(licensee.statuses, hasSize(1));
|
||||
assertThat(licensee.statuses.get(0).getMode(), is(License.OperationMode.TRIAL));
|
||||
assertThat(licensee.statuses.get(0).getLicenseState(), is(LicenseState.ENABLED));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// generate signed licenses
|
||||
License license = generateSignedLicense("gold", TimeValue.timeValueHours(1));
|
||||
TestUtils.registerAndAckSignedLicenses(licensesService, license, LicensesStatus.VALID);
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(licensee.statuses, hasSize(2));
|
||||
assertThat(licensee.statuses.get(1).getMode(), not(License.OperationMode.TRIAL));
|
||||
assertThat(licensee.statuses.get(1).getLicenseState(), is(LicenseState.ENABLED));
|
||||
}
|
||||
});
|
||||
|
||||
// remove signed licenses
|
||||
removeAndAckSignedLicenses(licensesService);
|
||||
assertBusy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertThat(licensee.statuses, hasSize(3));
|
||||
}
|
||||
});
|
||||
LicensesMetaData licensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE);
|
||||
assertThat(licensesMetaData.getLicense(), is(LicensesMetaData.LICENSE_TOMBSTONE));
|
||||
assertThat(licensee.statuses, hasSize(3));
|
||||
assertThat(licensee.statuses.get(2).getLicenseState(), is(LicenseState.DISABLED));
|
||||
assertThat(licensee.statuses.get(2).getMode(), is(License.OperationMode.MISSING));
|
||||
}
|
||||
|
||||
private void removeAndAckSignedLicenses(final LicensesService licensesService) {
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
final AtomicBoolean success = new AtomicBoolean(false);
|
||||
|
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.TestUtils;
|
||||
@ -12,21 +14,20 @@ import org.elasticsearch.license.plugin.TestUtils.AssertingLicensee;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class LicensesNotificationTests extends AbstractLicenseServiceTestCase {
|
||||
|
||||
public void testLicenseNotification() throws Exception {
|
||||
final License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(48));
|
||||
setInitialState(license);
|
||||
licensesService.start();
|
||||
int nLicensee = randomIntBetween(1, 3);
|
||||
AssertingLicensee[] assertingLicensees = new AssertingLicensee[nLicensee];
|
||||
for (int i = 0; i < assertingLicensees.length; i++) {
|
||||
assertingLicensees[i] = new AssertingLicensee("testLicenseNotification" + i, logger);
|
||||
licensesService.register(assertingLicensees[i]);
|
||||
}
|
||||
setInitialState(license, assertingLicensees);
|
||||
licensesService.start();
|
||||
for (int i = 0; i < assertingLicensees.length; i++) {
|
||||
assertLicenseStates(assertingLicensees[i], LicenseState.ENABLED);
|
||||
}
|
||||
clock.fastForward(TimeValue.timeValueMillis(license.expiryDate() - clock.millis()));
|
||||
@ -36,7 +37,7 @@ public class LicensesNotificationTests extends AbstractLicenseServiceTestCase {
|
||||
assertLicenseStates(assertingLicensee, LicenseState.ENABLED, LicenseState.GRACE_PERIOD);
|
||||
}
|
||||
clock.fastForward(TimeValue.timeValueMillis((license.expiryDate() +
|
||||
LicensesService.GRACE_PERIOD_DURATION.getMillis()) - clock.millis()));
|
||||
LicenseState.GRACE_PERIOD_DURATION.getMillis()) - clock.millis()));
|
||||
licensesService.onUpdate(licensesMetaData);
|
||||
for (AssertingLicensee assertingLicensee : assertingLicensees) {
|
||||
assertLicenseStates(assertingLicensee, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED);
|
||||
@ -44,12 +45,12 @@ public class LicensesNotificationTests extends AbstractLicenseServiceTestCase {
|
||||
clock.setTime(new DateTime(DateTimeZone.UTC));
|
||||
final License newLicense = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2));
|
||||
clock.fastForward(TimeValue.timeValueHours(1));
|
||||
licensesService.onUpdate(new LicensesMetaData(newLicense));
|
||||
LicensesMetaData licensesMetaData1 = new LicensesMetaData(newLicense);
|
||||
licensesService.onUpdate(licensesMetaData1);
|
||||
for (AssertingLicensee assertingLicensee : assertingLicensees) {
|
||||
assertLicenseStates(assertingLicensee, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED,
|
||||
LicenseState.ENABLED);
|
||||
}
|
||||
licensesService.stop();
|
||||
}
|
||||
|
||||
private void assertLicenseStates(AssertingLicensee licensee, LicenseState... states) {
|
||||
@ -88,4 +89,4 @@ public class LicensesNotificationTests extends AbstractLicenseServiceTestCase {
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import org.elasticsearch.common.UUIDs;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.discovery.DiscoveryModule;
|
||||
import org.elasticsearch.discovery.zen.ping.unicast.UnicastZenPing;
|
||||
import org.elasticsearch.xpack.monitoring.Monitoring;
|
||||
import org.elasticsearch.node.Node;
|
||||
@ -59,7 +60,8 @@ public abstract class TribeTransportTestCase extends ESIntegTestCase {
|
||||
protected final Settings nodeSettings(int nodeOrdinal) {
|
||||
final Settings.Builder builder = Settings.builder()
|
||||
.put(NetworkModule.HTTP_ENABLED.getKey(), false)
|
||||
.put(Node.NODE_LOCAL_SETTING.getKey(), true);
|
||||
.put("transport.type", "local")
|
||||
.put(DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey(), "local");
|
||||
List<String> enabledFeatures = enabledFeatures();
|
||||
for (String feature : ALL_FEATURES) {
|
||||
builder.put(XPackPlugin.featureEnabledSetting(feature), enabledFeatures.contains(feature));
|
||||
@ -99,7 +101,7 @@ public abstract class TribeTransportTestCase extends ESIntegTestCase {
|
||||
return TribeTransportTestCase.this.transportClientPlugins();
|
||||
}
|
||||
};
|
||||
final InternalTestCluster cluster2 = new InternalTestCluster(InternalTestCluster.configuredNodeMode(),
|
||||
final InternalTestCluster cluster2 = new InternalTestCluster(
|
||||
randomLong(), createTempDir(), true, 2, 2,
|
||||
UUIDs.randomBase64UUID(random()), nodeConfigurationSource, 1, false, "tribe_node2",
|
||||
getMockPlugins(), getClientWrapper());
|
||||
@ -131,12 +133,17 @@ public abstract class TribeTransportTestCase extends ESIntegTestCase {
|
||||
Settings merged = Settings.builder()
|
||||
.put("tribe.t1.cluster.name", internalCluster().getClusterName())
|
||||
.put("tribe.t2.cluster.name", cluster2.getClusterName())
|
||||
.put("tribe.t1.transport.type", "local")
|
||||
.put("tribe.t2.transport.type", "local")
|
||||
.put("tribe.t1.discovery.type", "local")
|
||||
.put("tribe.t2.discovery.type", "local")
|
||||
.put("tribe.blocks.write", false)
|
||||
.put(tribe1Defaults.build())
|
||||
.put(tribe2Defaults.build())
|
||||
.put(NetworkModule.HTTP_ENABLED.getKey(), false)
|
||||
.put(internalCluster().getDefaultSettings())
|
||||
.put("node.name", "tribe_node") // make sure we can identify threads from this node
|
||||
.put(Node.NODE_LOCAL_SETTING.getKey(), true)
|
||||
.put("transport.type", "local")
|
||||
.build();
|
||||
|
||||
final Node tribeNode = new Node(merged).start();
|
||||
|
@ -78,9 +78,7 @@ public class Monitoring implements ActionPlugin {
|
||||
if (enabled == false || transportClientMode || tribeNode) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Arrays.<Class<? extends LifecycleComponent>>asList(MonitoringLicensee.class,
|
||||
AgentService.class,
|
||||
CleanerService.class);
|
||||
return Arrays.<Class<? extends LifecycleComponent>>asList(AgentService.class, CleanerService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,15 +6,11 @@
|
||||
package org.elasticsearch.xpack.monitoring;
|
||||
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.logging.LoggerMessageFormat;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.core.License.OperationMode;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.Licensee;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
|
||||
/**
|
||||
* {@code MonitoringLicensee} determines whether certain features of Monitoring are enabled or disabled.
|
||||
@ -25,11 +21,10 @@ import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
* <li>Cleaning up (deleting) older indices.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class MonitoringLicensee extends AbstractLicenseeComponent<MonitoringLicensee> implements Licensee {
|
||||
public class MonitoringLicensee extends AbstractLicenseeComponent {
|
||||
|
||||
@Inject
|
||||
public MonitoringLicensee(Settings settings, LicenseeRegistry clientService) {
|
||||
super(settings, Monitoring.NAME, clientService);
|
||||
public MonitoringLicensee(Settings settings) {
|
||||
super(settings, Monitoring.NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,27 +42,25 @@ public class MonitoringLicensee extends AbstractLicenseeComponent<MonitoringLice
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] acknowledgmentMessages(License currentLicense, License newLicense) {
|
||||
switch (newLicense.operationMode()) {
|
||||
public String[] acknowledgmentMessages(OperationMode currentMode, OperationMode newMode) {
|
||||
switch (newMode) {
|
||||
case BASIC:
|
||||
if (currentLicense != null) {
|
||||
switch (currentLicense.operationMode()) {
|
||||
case TRIAL:
|
||||
case STANDARD:
|
||||
case GOLD:
|
||||
case PLATINUM:
|
||||
return new String[] {
|
||||
LoggerMessageFormat.format(
|
||||
"Multi-cluster support is disabled for clusters with [{}] license. If you are\n" +
|
||||
"running multiple clusters, users won't be able to access the clusters with\n" +
|
||||
"[{}] licenses from within a single X-Pack Kibana instance. You will have to deploy a\n" +
|
||||
"separate and dedicated X-pack Kibana instance for each [{}] cluster you wish to monitor.",
|
||||
newLicense.type(), newLicense.type(), newLicense.type()),
|
||||
LoggerMessageFormat.format(
|
||||
"Automatic index cleanup is locked to {} days for clusters with [{}] license.",
|
||||
MonitoringSettings.HISTORY_DURATION.getDefault(Settings.EMPTY).days(), newLicense.type())
|
||||
};
|
||||
}
|
||||
switch (currentMode) {
|
||||
case TRIAL:
|
||||
case STANDARD:
|
||||
case GOLD:
|
||||
case PLATINUM:
|
||||
return new String[] {
|
||||
LoggerMessageFormat.format(
|
||||
"Multi-cluster support is disabled for clusters with [{}] license. If you are\n" +
|
||||
"running multiple clusters, users won't be able to access the clusters with\n" +
|
||||
"[{}] licenses from within a single X-Pack Kibana instance. You will have to deploy a\n" +
|
||||
"separate and dedicated X-pack Kibana instance for each [{}] cluster you wish to monitor.",
|
||||
newMode, newMode, newMode),
|
||||
LoggerMessageFormat.format(
|
||||
"Automatic index cleanup is locked to {} days for clusters with [{}] license.",
|
||||
MonitoringSettings.HISTORY_DURATION.getDefault(Settings.EMPTY).days(), newMode)
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -26,11 +26,10 @@ public class MonitoringModule extends AbstractModule {
|
||||
XPackPlugin.bindFeatureSet(binder(), MonitoringFeatureSet.class);
|
||||
|
||||
if (enabled && transportClientMode == false) {
|
||||
bind(MonitoringLicensee.class).asEagerSingleton();
|
||||
bind(MonitoringSettings.class).asEagerSingleton();
|
||||
bind(AgentService.class).asEagerSingleton();
|
||||
bind(CleanerService.class).asEagerSingleton();
|
||||
} else {
|
||||
} else if (transportClientMode) {
|
||||
bind(MonitoringLicensee.class).toProvider(Providers.of(null));
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.plugin.core.LicenseUtils;
|
||||
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
|
||||
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollector;
|
||||
@ -40,16 +40,16 @@ public class ClusterStatsCollector extends AbstractCollector {
|
||||
|
||||
public static final String NAME = "cluster-stats-collector";
|
||||
|
||||
private final LicensesManagerService licensesManagerService;
|
||||
private final LicensesService licensesService;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
public ClusterStatsCollector(Settings settings, ClusterService clusterService,
|
||||
MonitoringSettings monitoringSettings, MonitoringLicensee licensee, InternalClient client,
|
||||
LicensesManagerService licensesManagerService) {
|
||||
LicensesService licensesService) {
|
||||
super(settings, NAME, clusterService, monitoringSettings, licensee);
|
||||
this.client = client;
|
||||
this.licensesManagerService = licensesManagerService;
|
||||
this.licensesService = licensesService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,7 +85,7 @@ public class ClusterStatsCollector extends AbstractCollector {
|
||||
clusterInfoDoc.setSourceNode(sourceNode);
|
||||
clusterInfoDoc.setClusterName(clusterService.getClusterName().value());
|
||||
clusterInfoDoc.setVersion(Version.CURRENT.toString());
|
||||
clusterInfoDoc.setLicense(licensesManagerService.getLicense());
|
||||
clusterInfoDoc.setLicense(licensesService.getLicense());
|
||||
clusterInfoDoc.setClusterStats(clusterStats);
|
||||
results.add(clusterInfoDoc);
|
||||
|
||||
|
@ -68,6 +68,8 @@ public class IndexStatsCollector extends AbstractCollector {
|
||||
.setSegments(true)
|
||||
.setStore(true)
|
||||
.setRefresh(true)
|
||||
.setQueryCache(true)
|
||||
.setRequestCache(true)
|
||||
.get(monitoringSettings.indexStatsTimeout());
|
||||
|
||||
long timestamp = System.currentTimeMillis();
|
||||
|
@ -26,12 +26,22 @@ public class IndexStatsResolver extends MonitoringIndexNameResolver.Timestamped<
|
||||
"index_stats.index",
|
||||
"index_stats.primaries.docs.count",
|
||||
"index_stats.primaries.fielddata.memory_size_in_bytes",
|
||||
"index_stats.primaries.fielddata.evictions",
|
||||
"index_stats.primaries.indexing.index_total",
|
||||
"index_stats.primaries.indexing.index_time_in_millis",
|
||||
"index_stats.primaries.indexing.throttle_time_in_millis",
|
||||
"index_stats.primaries.merges.total_size_in_bytes",
|
||||
"index_stats.primaries.query_cache.memory_size_in_bytes",
|
||||
"index_stats.primaries.query_cache.evictions",
|
||||
"index_stats.primaries.query_cache.hit_count",
|
||||
"index_stats.primaries.query_cache.miss_count",
|
||||
"index_stats.primaries.request_cache.memory_size_in_bytes",
|
||||
"index_stats.primaries.request_cache.evictions",
|
||||
"index_stats.primaries.request_cache.hit_count",
|
||||
"index_stats.primaries.request_cache.miss_count",
|
||||
"index_stats.primaries.search.query_total",
|
||||
"index_stats.primaries.search.query_time_in_millis",
|
||||
"index_stats.primaries.segments.count",
|
||||
"index_stats.primaries.segments.memory_in_bytes",
|
||||
"index_stats.primaries.segments.terms_memory_in_bytes",
|
||||
"index_stats.primaries.segments.stored_fields_memory_in_bytes",
|
||||
@ -47,12 +57,22 @@ public class IndexStatsResolver extends MonitoringIndexNameResolver.Timestamped<
|
||||
"index_stats.primaries.refresh.total_time_in_millis",
|
||||
"index_stats.total.docs.count",
|
||||
"index_stats.total.fielddata.memory_size_in_bytes",
|
||||
"index_stats.total.fielddata.evictions",
|
||||
"index_stats.total.indexing.index_total",
|
||||
"index_stats.total.indexing.index_time_in_millis",
|
||||
"index_stats.total.indexing.throttle_time_in_millis",
|
||||
"index_stats.total.merges.total_size_in_bytes",
|
||||
"index_stats.total.query_cache.memory_size_in_bytes",
|
||||
"index_stats.total.query_cache.evictions",
|
||||
"index_stats.total.query_cache.hit_count",
|
||||
"index_stats.total.query_cache.miss_count",
|
||||
"index_stats.total.request_cache.memory_size_in_bytes",
|
||||
"index_stats.total.request_cache.evictions",
|
||||
"index_stats.total.request_cache.hit_count",
|
||||
"index_stats.total.request_cache.miss_count",
|
||||
"index_stats.total.search.query_total",
|
||||
"index_stats.total.search.query_time_in_millis",
|
||||
"index_stats.total.segments.count",
|
||||
"index_stats.total.segments.memory_in_bytes",
|
||||
"index_stats.total.segments.terms_memory_in_bytes",
|
||||
"index_stats.total.segments.stored_fields_memory_in_bytes",
|
||||
|
@ -32,11 +32,21 @@ public class NodeStatsResolver extends MonitoringIndexNameResolver.Timestamped<N
|
||||
"node_stats.disk_threshold_watermark_high",
|
||||
// Node Stats
|
||||
"node_stats.indices.docs.count",
|
||||
"node_stats.indices.fielddata.memory_size_in_bytes",
|
||||
"node_stats.indices.fielddata.evictions",
|
||||
"node_stats.indices.store.size_in_bytes",
|
||||
"node_stats.indices.store.throttle_time_in_millis",
|
||||
"node_stats.indices.indexing.throttle_time_in_millis",
|
||||
"node_stats.indices.indexing.index_total",
|
||||
"node_stats.indices.indexing.index_time_in_millis",
|
||||
"node_stats.indices.query_cache.memory_size_in_bytes",
|
||||
"node_stats.indices.query_cache.evictions",
|
||||
"node_stats.indices.query_cache.hit_count",
|
||||
"node_stats.indices.query_cache.miss_count",
|
||||
"node_stats.indices.request_cache.memory_size_in_bytes",
|
||||
"node_stats.indices.request_cache.evictions",
|
||||
"node_stats.indices.request_cache.hit_count",
|
||||
"node_stats.indices.request_cache.miss_count",
|
||||
"node_stats.indices.search.query_total",
|
||||
"node_stats.indices.search.query_time_in_millis",
|
||||
"node_stats.indices.segments.count",
|
||||
|
@ -109,6 +109,9 @@
|
||||
"properties": {
|
||||
"memory_size_in_bytes": {
|
||||
"type": "long"
|
||||
},
|
||||
"evictions": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -142,6 +145,38 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"query_cache": {
|
||||
"properties": {
|
||||
"memory_size_in_bytes": {
|
||||
"type": "long"
|
||||
},
|
||||
"evictions": {
|
||||
"type": "long"
|
||||
},
|
||||
"hit_count": {
|
||||
"type": "long"
|
||||
},
|
||||
"miss_count": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request_cache": {
|
||||
"properties": {
|
||||
"memory_size_in_bytes": {
|
||||
"type": "long"
|
||||
},
|
||||
"evictions": {
|
||||
"type": "long"
|
||||
},
|
||||
"hit_count": {
|
||||
"type": "long"
|
||||
},
|
||||
"miss_count": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"search": {
|
||||
"properties": {
|
||||
"query_total": {
|
||||
@ -154,6 +189,9 @@
|
||||
},
|
||||
"segments": {
|
||||
"properties": {
|
||||
"count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"memory_in_bytes": {
|
||||
"type": "long"
|
||||
},
|
||||
@ -205,6 +243,9 @@
|
||||
"properties": {
|
||||
"memory_size_in_bytes": {
|
||||
"type": "long"
|
||||
},
|
||||
"evictions": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -238,6 +279,38 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"query_cache": {
|
||||
"properties": {
|
||||
"memory_size_in_bytes": {
|
||||
"type": "long"
|
||||
},
|
||||
"evictions": {
|
||||
"type": "long"
|
||||
},
|
||||
"hit_count": {
|
||||
"type": "long"
|
||||
},
|
||||
"miss_count": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request_cache": {
|
||||
"properties": {
|
||||
"memory_size_in_bytes": {
|
||||
"type": "long"
|
||||
},
|
||||
"evictions": {
|
||||
"type": "long"
|
||||
},
|
||||
"hit_count": {
|
||||
"type": "long"
|
||||
},
|
||||
"miss_count": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"search": {
|
||||
"properties": {
|
||||
"query_total": {
|
||||
@ -250,6 +323,9 @@
|
||||
},
|
||||
"segments": {
|
||||
"properties": {
|
||||
"count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"memory_in_bytes": {
|
||||
"type": "long"
|
||||
},
|
||||
@ -374,6 +450,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"fielddata" : {
|
||||
"properties": {
|
||||
"memory_size_in_bytes": {
|
||||
"type": "long"
|
||||
},
|
||||
"evictions": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"indexing": {
|
||||
"properties": {
|
||||
"index_time_in_millis": {
|
||||
@ -387,6 +473,38 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"query_cache": {
|
||||
"properties": {
|
||||
"memory_size_in_bytes": {
|
||||
"type": "long"
|
||||
},
|
||||
"evictions": {
|
||||
"type": "long"
|
||||
},
|
||||
"hit_count": {
|
||||
"type": "long"
|
||||
},
|
||||
"miss_count": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request_cache": {
|
||||
"properties": {
|
||||
"memory_size_in_bytes": {
|
||||
"type": "long"
|
||||
},
|
||||
"evictions": {
|
||||
"type": "long"
|
||||
},
|
||||
"hit_count": {
|
||||
"type": "long"
|
||||
},
|
||||
"miss_count": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"search": {
|
||||
"properties": {
|
||||
"query_time_in_millis": {
|
||||
@ -400,7 +518,7 @@
|
||||
"segments": {
|
||||
"properties": {
|
||||
"count": {
|
||||
"type": "long"
|
||||
"type": "integer"
|
||||
},
|
||||
"memory_in_bytes": {
|
||||
"type": "long"
|
||||
|
@ -5,43 +5,45 @@
|
||||
*/
|
||||
package org.elasticsearch.xpack.monitoring.agent.collector;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.RandomizedTest;
|
||||
import com.carrotsearch.randomizedtesting.SysGlobals;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.cluster.block.ClusterBlocks;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
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.unit.TimeValue;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.Licensing;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.Licensee;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.rest.RestHandler;
|
||||
import org.elasticsearch.xpack.security.InternalClient;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
|
||||
import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.RandomizedTest;
|
||||
import com.carrotsearch.randomizedtesting.SysGlobals;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.cluster.block.ClusterBlocks;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.Licensing;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.Licensee;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.rest.RestHandler;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.graph.GraphLicensee;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
|
||||
import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase;
|
||||
import org.elasticsearch.xpack.security.InternalClient;
|
||||
import org.elasticsearch.xpack.security.SecurityLicenseState;
|
||||
import org.elasticsearch.xpack.support.clock.Clock;
|
||||
import org.elasticsearch.xpack.watcher.WatcherLicensee;
|
||||
import org.junit.Before;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.elasticsearch.common.unit.TimeValue.timeValueMinutes;
|
||||
|
||||
@ -57,7 +59,6 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return Settings.builder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put(NetworkModule.HTTP_ENABLED.getKey(), false)
|
||||
.put(MonitoringSettings.INTERVAL.getKey(), "-1")
|
||||
.build();
|
||||
}
|
||||
@ -111,7 +112,7 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
|
||||
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
|
||||
service.onChange(license.operationMode(), LicenseState.ENABLED);
|
||||
}
|
||||
for (LicensesManagerServiceForCollectors service : internalCluster().getInstances(LicensesManagerServiceForCollectors.class)) {
|
||||
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
|
||||
service.update(license);
|
||||
}
|
||||
}
|
||||
@ -124,7 +125,7 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
|
||||
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
|
||||
service.onChange(license.operationMode(), LicenseState.GRACE_PERIOD);
|
||||
}
|
||||
for (LicensesManagerServiceForCollectors service : internalCluster().getInstances(LicensesManagerServiceForCollectors.class)) {
|
||||
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
|
||||
service.update(license);
|
||||
}
|
||||
}
|
||||
@ -137,7 +138,7 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
|
||||
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
|
||||
service.onChange(license.operationMode(), LicenseState.DISABLED);
|
||||
}
|
||||
for (LicensesManagerServiceForCollectors service : internalCluster().getInstances(LicensesManagerServiceForCollectors.class)) {
|
||||
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
|
||||
service.update(license);
|
||||
}
|
||||
}
|
||||
@ -150,7 +151,7 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
|
||||
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
|
||||
service.onChange(license.operationMode(), LicenseState.DISABLED);
|
||||
}
|
||||
for (LicensesManagerServiceForCollectors service : internalCluster().getInstances(LicensesManagerServiceForCollectors.class)) {
|
||||
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
|
||||
service.update(license);
|
||||
}
|
||||
}
|
||||
@ -191,16 +192,19 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
|
||||
|
||||
@Override
|
||||
public Collection<Module> nodeModules() {
|
||||
return Collections.<Module>singletonList(new AbstractModule() {
|
||||
return Collections.singletonList(b -> b.bind(LicensesService.class).to(LicenseServiceForCollectors.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(LicenseServiceForCollectors.class).asEagerSingleton();
|
||||
bind(LicenseeRegistry.class).to(LicenseServiceForCollectors.class);
|
||||
bind(LicensesManagerServiceForCollectors.class).asEagerSingleton();
|
||||
bind(LicensesManagerService.class).to(LicensesManagerServiceForCollectors.class);
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public Collection<Object> createComponents(ClusterService clusterService, Clock clock, Environment environment,
|
||||
ResourceWatcherService resourceWatcherService,
|
||||
SecurityLicenseState securityLicenseState) {
|
||||
WatcherLicensee watcherLicensee = new WatcherLicensee(settings);
|
||||
MonitoringLicensee monitoringLicensee = new MonitoringLicensee(settings);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(settings);
|
||||
LicensesService licensesService = new LicenseServiceForCollectors(settings, environment,
|
||||
resourceWatcherService, Arrays.asList(watcherLicensee, monitoringLicensee, graphLicensee));
|
||||
return Arrays.asList(licensesService, watcherLicensee, monitoringLicensee, graphLicensee);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -212,11 +216,6 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
|
||||
public List<Class<? extends RestHandler>> getRestHandlers() {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public static class InternalXPackPlugin extends XPackPlugin {
|
||||
@ -227,18 +226,16 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
|
||||
}
|
||||
}
|
||||
|
||||
public static class LicenseServiceForCollectors extends AbstractComponent implements LicenseeRegistry {
|
||||
public static class LicenseServiceForCollectors extends LicensesService {
|
||||
|
||||
private final List<Licensee> licensees = new ArrayList<>();
|
||||
private final List<Licensee> licensees;
|
||||
private volatile License license;
|
||||
|
||||
@Inject
|
||||
public LicenseServiceForCollectors(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Licensee licensee) {
|
||||
licensees.add(licensee);
|
||||
public LicenseServiceForCollectors(Settings settings, Environment env,
|
||||
ResourceWatcherService resourceWatcherService, List<Licensee> licensees) {
|
||||
super(settings, null, null, env, resourceWatcherService, licensees);
|
||||
this.licensees = licensees;
|
||||
}
|
||||
|
||||
public void onChange(License.OperationMode operationMode, LicenseState state) {
|
||||
@ -246,14 +243,9 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
|
||||
licensee.onChange(new Licensee.Status(operationMode, state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class LicensesManagerServiceForCollectors implements LicensesManagerService {
|
||||
|
||||
private volatile License license;
|
||||
|
||||
@Override
|
||||
public LicenseState licenseState() {
|
||||
public Licensee.Status licenseeStatus() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -265,5 +257,11 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
|
||||
public synchronized void update(License license) {
|
||||
this.license = license;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() {}
|
||||
|
||||
@Override
|
||||
protected void doStop() {}
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,13 @@
|
||||
*/
|
||||
package org.elasticsearch.xpack.monitoring.agent.collector.cluster;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase.BadApple;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoredSystem;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
|
||||
@ -17,8 +19,6 @@ import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollector;
|
||||
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollectorTestCase;
|
||||
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
@ -133,7 +133,7 @@ public class ClusterStatsCollectorTests extends AbstractCollectorTestCase {
|
||||
internalCluster().getInstance(MonitoringSettings.class, nodeId),
|
||||
internalCluster().getInstance(MonitoringLicensee.class, nodeId),
|
||||
securedClient(nodeId),
|
||||
internalCluster().getInstance(LicensesManagerService.class, nodeId));
|
||||
internalCluster().getInstance(LicensesService.class, nodeId));
|
||||
}
|
||||
|
||||
private void assertCanCollect(AbstractCollector collector, Class<?>... classes) {
|
||||
|
@ -16,6 +16,7 @@ import org.elasticsearch.common.transport.LocalTransportAddress;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.cache.query.QueryCacheStats;
|
||||
import org.elasticsearch.index.cache.request.RequestCacheStats;
|
||||
import org.elasticsearch.index.engine.SegmentsStats;
|
||||
import org.elasticsearch.index.fielddata.FieldDataStats;
|
||||
import org.elasticsearch.index.merge.MergeStats;
|
||||
@ -86,6 +87,7 @@ public class IndexStatsResolverTests extends MonitoringIndexNameResolverTestCase
|
||||
CommonStats stats = new CommonStats();
|
||||
stats.fieldData = new FieldDataStats();
|
||||
stats.queryCache = new QueryCacheStats();
|
||||
stats.requestCache = new RequestCacheStats();
|
||||
stats.docs = new DocsStats();
|
||||
stats.store = new StoreStats();
|
||||
stats.indexing = new IndexingStats();
|
||||
|
@ -18,6 +18,7 @@ import org.elasticsearch.common.transport.LocalTransportAddress;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.cache.query.QueryCacheStats;
|
||||
import org.elasticsearch.index.cache.request.RequestCacheStats;
|
||||
import org.elasticsearch.index.engine.SegmentsStats;
|
||||
import org.elasticsearch.index.fielddata.FieldDataStats;
|
||||
import org.elasticsearch.index.search.stats.SearchStats;
|
||||
@ -113,6 +114,7 @@ public class NodeStatsResolverTests extends MonitoringIndexNameResolverTestCase<
|
||||
CommonStats stats = new CommonStats();
|
||||
stats.fieldData = new FieldDataStats();
|
||||
stats.queryCache = new QueryCacheStats();
|
||||
stats.requestCache = new RequestCacheStats();
|
||||
stats.docs = new DocsStats();
|
||||
stats.store = new StoreStats();
|
||||
stats.indexing = new IndexingStats();
|
||||
|
@ -10,12 +10,16 @@ import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.xpack.MockNetty3Plugin;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
|
||||
import org.elasticsearch.xpack.monitoring.agent.AgentService;
|
||||
import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
@ -44,6 +48,13 @@ public class MonitoringSettingsTests extends MonitoringIntegTestCase {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
||||
ArrayList<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
|
||||
plugins.add(MockNetty3Plugin.class); // for http
|
||||
return plugins;
|
||||
}
|
||||
|
||||
private Settings monitoringSettings() {
|
||||
return Settings.builder()
|
||||
.put(MonitoringSettings.INTERVAL.getKey(), interval)
|
||||
|
@ -7,24 +7,28 @@ package org.elasticsearch.xpack.monitoring.license;
|
||||
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.Licensing;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.Licensee;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.rest.RestHandler;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.graph.GraphLicensee;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
|
||||
import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase;
|
||||
import org.elasticsearch.xpack.security.SecurityLicenseState;
|
||||
import org.elasticsearch.xpack.support.clock.Clock;
|
||||
import org.elasticsearch.xpack.watcher.WatcherLicensee;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -92,7 +96,19 @@ public class LicenseIntegrationTests extends MonitoringIntegTestCase {
|
||||
|
||||
@Override
|
||||
public Collection<Module> nodeModules() {
|
||||
return Collections.<Module>singletonList(new InternalLicenseModule());
|
||||
return Collections.singletonList(b -> b.bind(LicensesService.class).to(MockLicenseService.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Object> createComponents(ClusterService clusterService, Clock clock, Environment environment,
|
||||
ResourceWatcherService resourceWatcherService,
|
||||
SecurityLicenseState securityLicenseState) {
|
||||
WatcherLicensee watcherLicensee = new WatcherLicensee(settings);
|
||||
MonitoringLicensee monitoringLicensee = new MonitoringLicensee(settings);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(settings);
|
||||
LicensesService licensesService = new MockLicenseService(settings, environment, resourceWatcherService,
|
||||
Arrays.asList(watcherLicensee, monitoringLicensee, graphLicensee));
|
||||
return Arrays.asList(licensesService, watcherLicensee, monitoringLicensee, graphLicensee);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -104,36 +120,17 @@ public class LicenseIntegrationTests extends MonitoringIntegTestCase {
|
||||
public List<Class<? extends RestHandler>> getRestHandlers() {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class InternalLicenseModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(MockLicenseService.class).asEagerSingleton();
|
||||
bind(LicenseeRegistry.class).to(MockLicenseService.class);
|
||||
bind(LicensesManagerService.class).to(MockLicenseService.class);
|
||||
}
|
||||
}
|
||||
public static class MockLicenseService extends LicensesService {
|
||||
|
||||
public static class MockLicenseService extends AbstractComponent implements LicenseeRegistry, LicensesManagerService {
|
||||
|
||||
private final List<Licensee> licensees = new ArrayList<>();
|
||||
private final List<Licensee> licensees;
|
||||
|
||||
@Inject
|
||||
public MockLicenseService(Settings settings) {
|
||||
super(settings);
|
||||
enable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Licensee licensee) {
|
||||
licensees.add(licensee);
|
||||
public MockLicenseService(Settings settings, Environment environment,
|
||||
ResourceWatcherService resourceWatcherService, List<Licensee> licensees) {
|
||||
super(settings, null, null, environment, resourceWatcherService, licensees);
|
||||
this.licensees = licensees;
|
||||
enable();
|
||||
}
|
||||
|
||||
@ -151,7 +148,7 @@ public class LicenseIntegrationTests extends MonitoringIntegTestCase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LicenseState licenseState() {
|
||||
public Licensee.Status licenseeStatus() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -159,6 +156,12 @@ public class LicenseIntegrationTests extends MonitoringIntegTestCase {
|
||||
public License getLicense() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() {}
|
||||
|
||||
@Override
|
||||
protected void doStop() {}
|
||||
}
|
||||
|
||||
public static class InternalXPackPlugin extends XPackPlugin {
|
||||
|
@ -10,7 +10,6 @@ import org.elasticsearch.license.core.License.OperationMode;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.Licensee.Status;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
@ -18,7 +17,6 @@ import java.util.function.Predicate;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
@ -27,8 +25,7 @@ import static org.mockito.Mockito.when;
|
||||
* If you change the behavior of these tests, then it means that licensing changes for Monitoring!
|
||||
*/
|
||||
public class MonitoringLicenseeTests extends AbstractLicenseeTestCase {
|
||||
private final LicenseeRegistry registry = mock(LicenseeRegistry.class);
|
||||
private final MonitoringLicensee licensee = new MonitoringLicensee(Settings.EMPTY, registry);
|
||||
private final MonitoringLicensee licensee = new MonitoringLicensee(Settings.EMPTY);
|
||||
|
||||
public void testAcknowledgementMessagesToAnyFromFreeIsNoOp() {
|
||||
assertEmptyAck(OperationMode.BASIC, randomMode(), licensee);
|
||||
@ -93,7 +90,6 @@ public class MonitoringLicenseeTests extends AbstractLicenseeTestCase {
|
||||
assertThat(predicate.test(licensee), equalTo(expected));
|
||||
|
||||
verify(status).getLicenseState();
|
||||
verifyNoMoreInteractions(registry);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,6 +108,5 @@ public class MonitoringLicenseeTests extends AbstractLicenseeTestCase {
|
||||
assertThat(predicate.test(licensee), equalTo(expected));
|
||||
|
||||
verify(status).getMode();
|
||||
verifyNoMoreInteractions(registry);
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ public class MonitoringInternalClientTests extends MonitoringIntegTestCase {
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return Settings.builder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put(NetworkModule.HTTP_ENABLED.getKey(), false)
|
||||
.put(MonitoringSettings.INTERVAL.getKey(), "-1")
|
||||
.build();
|
||||
}
|
||||
|
@ -11,10 +11,14 @@ import org.elasticsearch.client.Response;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.xpack.MockNetty3Plugin;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
|
||||
import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractValue;
|
||||
@ -41,6 +45,13 @@ public class MonitoringSettingsFilterTests extends MonitoringIntegTestCase {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
||||
ArrayList<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
|
||||
plugins.add(MockNetty3Plugin.class); // for http
|
||||
return plugins;
|
||||
}
|
||||
|
||||
public void testGetSettingsFiltered() throws Exception {
|
||||
Header[] headers;
|
||||
if (securityEnabled) {
|
||||
|
@ -10,6 +10,7 @@ setup:
|
||||
cluster.health:
|
||||
index: ".monitoring-data-*"
|
||||
wait_for_active_shards: 1
|
||||
timeout: 60s
|
||||
|
||||
---
|
||||
"Bulk indexing of monitoring data":
|
||||
|
104
elasticsearch/x-pack/security/bin/x-pack/certgen
Normal file
104
elasticsearch/x-pack/security/bin/x-pack/certgen
Normal file
@ -0,0 +1,104 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 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.
|
||||
|
||||
SCRIPT="$0"
|
||||
|
||||
# SCRIPT may be an arbitrarily deep series of symlinks. Loop until we have the concrete path.
|
||||
while [ -h "$SCRIPT" ] ; do
|
||||
ls=`ls -ld "$SCRIPT"`
|
||||
# Drop everything prior to ->
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
SCRIPT="$link"
|
||||
else
|
||||
SCRIPT=`dirname "$SCRIPT"`/"$link"
|
||||
fi
|
||||
done
|
||||
|
||||
# determine elasticsearch home
|
||||
ES_HOME=`dirname "$SCRIPT"`/../..
|
||||
|
||||
# make ELASTICSEARCH_HOME absolute
|
||||
ES_HOME=`cd "$ES_HOME"; pwd`
|
||||
|
||||
# If an include wasn't specified in the environment, then search for one...
|
||||
if [ "x$ES_INCLUDE" = "x" ]; then
|
||||
# Locations (in order) to use when searching for an include file.
|
||||
for include in /usr/share/elasticsearch/elasticsearch.in.sh \
|
||||
/usr/local/share/elasticsearch/elasticsearch.in.sh \
|
||||
/opt/elasticsearch/elasticsearch.in.sh \
|
||||
~/.elasticsearch.in.sh \
|
||||
"`dirname "$0"`"/../elasticsearch.in.sh \
|
||||
"$ES_HOME/bin/elasticsearch.in.sh"; do
|
||||
if [ -r "$include" ]; then
|
||||
. "$include"
|
||||
break
|
||||
fi
|
||||
done
|
||||
# ...otherwise, source the specified include.
|
||||
elif [ -r "$ES_INCLUDE" ]; then
|
||||
. "$ES_INCLUDE"
|
||||
fi
|
||||
|
||||
if [ -x "$JAVA_HOME/bin/java" ]; then
|
||||
JAVA="$JAVA_HOME/bin/java"
|
||||
else
|
||||
JAVA=`which java`
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVA" ]; then
|
||||
echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$ES_CLASSPATH" ]; then
|
||||
echo "You must set the ES_CLASSPATH var" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$CONF_DIR" ]; then
|
||||
# Try to read package config files
|
||||
if [ -f "/etc/sysconfig/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
|
||||
. "/etc/sysconfig/elasticsearch"
|
||||
elif [ -f "/etc/default/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
|
||||
. "/etc/default/elasticsearch"
|
||||
fi
|
||||
fi
|
||||
|
||||
export HOSTNAME=`hostname -s`
|
||||
|
||||
# include x-pack jars in classpath
|
||||
ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/x-pack/*"
|
||||
|
||||
# don't let JAVA_TOOL_OPTIONS slip in (e.g. crazy agents in ubuntu)
|
||||
# works around https://bugs.launchpad.net/ubuntu/+source/jayatana/+bug/1441487
|
||||
if [ "x$JAVA_TOOL_OPTIONS" != "x" ]; then
|
||||
echo "Warning: Ignoring JAVA_TOOL_OPTIONS=$JAVA_TOOL_OPTIONS"
|
||||
echo "Please pass JVM parameters via ES_JAVA_OPTS instead"
|
||||
unset JAVA_TOOL_OPTIONS
|
||||
fi
|
||||
|
||||
# CONF_FILE setting was removed
|
||||
if [ ! -z "$CONF_FILE" ]; then
|
||||
echo "CONF_FILE setting is no longer supported. elasticsearch.yml must be placed in the config directory and cannot be renamed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
declare -a args=("$@")
|
||||
|
||||
if [ -e "$CONF_DIR" ]; then
|
||||
args=("${args[@]}" -Edefault.path.conf="$CONF_DIR")
|
||||
fi
|
||||
|
||||
cd "$ES_HOME" > /dev/null
|
||||
"$JAVA" $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" org.elasticsearch.xpack.security.ssl.CertificateTool "${args[@]}"
|
||||
status=$?
|
||||
cd - > /dev/null
|
||||
exit $status
|
BIN
elasticsearch/x-pack/security/bin/x-pack/certgen.bat
Normal file
BIN
elasticsearch/x-pack/security/bin/x-pack/certgen.bat
Normal file
Binary file not shown.
@ -59,15 +59,17 @@ if [ -z "$ES_CLASSPATH" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Try to read package config files
|
||||
if [ -f "/etc/sysconfig/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
if [ -z "$CONF_DIR" ]; then
|
||||
# Try to read package config files
|
||||
if [ -f "/etc/sysconfig/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
|
||||
. "/etc/sysconfig/elasticsearch"
|
||||
elif [ -f "/etc/default/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
. "/etc/sysconfig/elasticsearch"
|
||||
elif [ -f "/etc/default/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
|
||||
. "/etc/default/elasticsearch"
|
||||
. "/etc/default/elasticsearch"
|
||||
fi
|
||||
fi
|
||||
|
||||
export HOSTNAME=`hostname -s`
|
||||
|
@ -59,15 +59,17 @@ if [ -z "$ES_CLASSPATH" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Try to read package config files
|
||||
if [ -f "/etc/sysconfig/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
if [ -z "$CONF_DIR" ]; then
|
||||
# Try to read package config files
|
||||
if [ -f "/etc/sysconfig/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
|
||||
. "/etc/sysconfig/elasticsearch"
|
||||
elif [ -f "/etc/default/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
. "/etc/sysconfig/elasticsearch"
|
||||
elif [ -f "/etc/default/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
|
||||
. "/etc/default/elasticsearch"
|
||||
. "/etc/default/elasticsearch"
|
||||
fi
|
||||
fi
|
||||
|
||||
export HOSTNAME=`hostname -s`
|
||||
|
@ -59,15 +59,17 @@ if [ -z "$ES_CLASSPATH" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Try to read package config files
|
||||
if [ -f "/etc/sysconfig/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
if [ -z "$CONF_DIR" ]; then
|
||||
# Try to read package config files
|
||||
if [ -f "/etc/sysconfig/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
|
||||
. "/etc/sysconfig/elasticsearch"
|
||||
elif [ -f "/etc/default/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
. "/etc/sysconfig/elasticsearch"
|
||||
elif [ -f "/etc/default/elasticsearch" ]; then
|
||||
CONF_DIR=/etc/elasticsearch
|
||||
|
||||
. "/etc/default/elasticsearch"
|
||||
. "/etc/default/elasticsearch"
|
||||
fi
|
||||
fi
|
||||
|
||||
export HOSTNAME=`hostname -s`
|
||||
|
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package org.elasticsearch.xpack.security;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
@ -13,60 +15,57 @@ import org.elasticsearch.action.ActionRequestBuilder;
|
||||
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.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationService;
|
||||
import org.elasticsearch.xpack.security.user.XPackUser;
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.elasticsearch.xpack.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.security.authc.InternalAuthenticationService;
|
||||
import org.elasticsearch.xpack.security.crypto.CryptoService;
|
||||
import org.elasticsearch.xpack.security.user.XPackUser;
|
||||
|
||||
/**
|
||||
* A special filter client for internal node communication which adds the internal xpack user to the headers.
|
||||
* An optionally secured client for internal node communication.
|
||||
*
|
||||
* When secured, the XPack user is added to the execution context before each action is executed.
|
||||
*/
|
||||
public interface InternalClient extends Client {
|
||||
public class InternalClient extends FilterClient {
|
||||
|
||||
private final CryptoService cryptoService;
|
||||
private final boolean signUserHeader;
|
||||
private final String nodeName;
|
||||
|
||||
/**
|
||||
* An insecured internal client, baseically simply delegates to the normal ES client
|
||||
* without doing anything extra.
|
||||
* Constructs an InternalClient.
|
||||
* If {@code cryptoService} is non-null, the client is secure. Otherwise this client is a passthrough.
|
||||
*/
|
||||
class Insecure extends FilterClient implements InternalClient {
|
||||
|
||||
@Inject
|
||||
public Insecure(Settings settings, ThreadPool threadPool, Client in) {
|
||||
super(settings, threadPool, in);
|
||||
}
|
||||
public InternalClient(Settings settings, ThreadPool threadPool, Client in, CryptoService cryptoService) {
|
||||
super(settings, threadPool, in);
|
||||
this.cryptoService = cryptoService;
|
||||
this.signUserHeader = InternalAuthenticationService.SIGN_USER_HEADER.get(settings);
|
||||
this.nodeName = Node.NODE_NAME_SETTING.get(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* A secured internal client that binds the internal XPack user to the current
|
||||
* execution context, before the action is executed.
|
||||
*/
|
||||
class Secure extends FilterClient implements InternalClient {
|
||||
@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) {
|
||||
|
||||
private final AuthenticationService authcService;
|
||||
|
||||
@Inject
|
||||
public Secure(Settings settings, ThreadPool threadPool, Client in, AuthenticationService authcService) {
|
||||
super(settings, threadPool, in);
|
||||
this.authcService = authcService;
|
||||
if (cryptoService == null) {
|
||||
super.doExecute(action, request, listener);
|
||||
return;
|
||||
}
|
||||
|
||||
@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 {
|
||||
authcService.attachUserIfMissing(XPackUser.INSTANCE);
|
||||
} catch (IOException ioe) {
|
||||
throw new ElasticsearchException("failed to attach internal user to request", ioe);
|
||||
}
|
||||
super.doExecute(action, request, listener);
|
||||
try (ThreadContext.StoredContext ctx = threadPool().getThreadContext().stashContext()) {
|
||||
try {
|
||||
Authentication authentication = new Authentication(XPackUser.INSTANCE,
|
||||
new Authentication.RealmRef("__attach", "__attach", nodeName), null);
|
||||
authentication.writeToContextIfMissing(threadPool().getThreadContext(), cryptoService, signUserHeader);
|
||||
} catch (IOException ioe) {
|
||||
throw new ElasticsearchException("failed to attach internal user to request", ioe);
|
||||
}
|
||||
super.doExecute(action, request, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,14 +10,20 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.action.support.ActionFilter;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.Booleans;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
@ -34,9 +40,14 @@ import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.index.IndexModule;
|
||||
import org.elasticsearch.ingest.Processor;
|
||||
import org.elasticsearch.plugins.ActionPlugin;
|
||||
import org.elasticsearch.plugins.IngestPlugin;
|
||||
import org.elasticsearch.rest.RestHandler;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.extensions.XPackExtension;
|
||||
import org.elasticsearch.xpack.security.action.SecurityActionModule;
|
||||
import org.elasticsearch.xpack.security.action.filter.SecurityActionFilter;
|
||||
import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheAction;
|
||||
@ -59,19 +70,28 @@ import org.elasticsearch.xpack.security.action.user.TransportChangePasswordActio
|
||||
import org.elasticsearch.xpack.security.action.user.TransportDeleteUserAction;
|
||||
import org.elasticsearch.xpack.security.action.user.TransportGetUsersAction;
|
||||
import org.elasticsearch.xpack.security.action.user.TransportPutUserAction;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailModule;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
|
||||
import org.elasticsearch.xpack.security.audit.index.IndexNameResolver;
|
||||
import org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationModule;
|
||||
import org.elasticsearch.xpack.security.authc.InternalAuthenticationService;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
import org.elasticsearch.xpack.security.authc.Realms;
|
||||
import org.elasticsearch.xpack.security.authc.activedirectory.ActiveDirectoryRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.authc.file.FileRealm;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.LdapRealm;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.SessionFactory;
|
||||
import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.xpack.security.authz.AuthorizationModule;
|
||||
import org.elasticsearch.xpack.security.authz.InternalAuthorizationService;
|
||||
import org.elasticsearch.xpack.security.authz.accesscontrol.SetSecurityUserProcessor;
|
||||
import org.elasticsearch.xpack.security.authz.accesscontrol.OptOutQueryCache;
|
||||
import org.elasticsearch.xpack.security.authz.accesscontrol.SecurityIndexSearcherWrapper;
|
||||
import org.elasticsearch.xpack.security.authz.store.FileRolesStore;
|
||||
@ -88,15 +108,16 @@ import org.elasticsearch.xpack.security.rest.action.user.RestChangePasswordActio
|
||||
import org.elasticsearch.xpack.security.rest.action.user.RestDeleteUserAction;
|
||||
import org.elasticsearch.xpack.security.rest.action.user.RestGetUsersAction;
|
||||
import org.elasticsearch.xpack.security.rest.action.user.RestPutUserAction;
|
||||
import org.elasticsearch.xpack.security.ssl.ClientSSLService;
|
||||
import org.elasticsearch.xpack.security.ssl.SSLConfiguration;
|
||||
import org.elasticsearch.xpack.security.ssl.SSLModule;
|
||||
import org.elasticsearch.xpack.security.ssl.ServerSSLService;
|
||||
import org.elasticsearch.xpack.security.support.OptionalSettings;
|
||||
import org.elasticsearch.xpack.security.transport.SecurityClientTransportService;
|
||||
import org.elasticsearch.xpack.security.transport.SecurityServerTransportService;
|
||||
import org.elasticsearch.xpack.security.transport.SecurityTransportModule;
|
||||
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
|
||||
import org.elasticsearch.xpack.security.transport.netty.SecurityNettyHttpServerTransport;
|
||||
import org.elasticsearch.xpack.security.transport.netty.SecurityNettyTransport;
|
||||
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3HttpServerTransport;
|
||||
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3Transport;
|
||||
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
@ -107,7 +128,7 @@ import static java.util.Collections.singletonList;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Security implements ActionPlugin {
|
||||
public class Security implements ActionPlugin, IngestPlugin {
|
||||
|
||||
private static final ESLogger logger = Loggers.getLogger(XPackPlugin.class);
|
||||
|
||||
@ -115,14 +136,24 @@ public class Security implements ActionPlugin {
|
||||
public static final String DLS_FLS_FEATURE = "security.dls_fls";
|
||||
public static final Setting<Optional<String>> USER_SETTING = OptionalSettings.createString(setting("user"), Property.NodeScope);
|
||||
|
||||
public static final Setting<Boolean> AUDIT_ENABLED_SETTING =
|
||||
Setting.boolSetting(featureEnabledSetting("audit"), false, Property.NodeScope);
|
||||
public static final Setting<List<String>> AUDIT_OUTPUTS_SETTING =
|
||||
Setting.listSetting(setting("audit.outputs"),
|
||||
s -> s.getAsMap().containsKey(setting("audit.outputs")) ?
|
||||
Collections.emptyList() : Collections.singletonList(LoggingAuditTrail.NAME),
|
||||
Function.identity(), Property.NodeScope);
|
||||
|
||||
private final Settings settings;
|
||||
private final Environment env;
|
||||
private final boolean enabled;
|
||||
private final boolean transportClientMode;
|
||||
private SecurityLicenseState securityLicenseState;
|
||||
private final SecurityLicenseState securityLicenseState;
|
||||
private final CryptoService cryptoService;
|
||||
|
||||
public Security(Settings settings, Environment env) throws IOException {
|
||||
this.settings = settings;
|
||||
this.env = env;
|
||||
this.transportClientMode = XPackPlugin.transportClientMode(settings);
|
||||
this.enabled = XPackPlugin.featureEnabled(settings, NAME, true);
|
||||
if (enabled && transportClientMode == false) {
|
||||
@ -131,6 +162,19 @@ public class Security implements ActionPlugin {
|
||||
} else {
|
||||
cryptoService = null;
|
||||
}
|
||||
securityLicenseState = new SecurityLicenseState();
|
||||
}
|
||||
|
||||
public CryptoService getCryptoService() {
|
||||
return cryptoService;
|
||||
}
|
||||
|
||||
public SecurityLicenseState getSecurityLicenseState() {
|
||||
return securityLicenseState;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public Collection<Module> nodeModules() {
|
||||
@ -140,18 +184,31 @@ public class Security implements ActionPlugin {
|
||||
if (enabled == false) {
|
||||
return modules;
|
||||
}
|
||||
modules.add(new SecurityModule(settings, securityLicenseState));
|
||||
modules.add(new SecurityModule(settings));
|
||||
modules.add(new SecurityTransportModule(settings));
|
||||
modules.add(new SSLModule(settings));
|
||||
modules.add(b -> {
|
||||
// for transport client we still must inject these ssl classes with guice
|
||||
b.bind(ServerSSLService.class).toProvider(Providers.<ServerSSLService>of(null));
|
||||
b.bind(ClientSSLService.class).toInstance(
|
||||
new ClientSSLService(settings, null, new SSLConfiguration.Global(settings), null));
|
||||
});
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
||||
modules.add(new AuthenticationModule(settings));
|
||||
modules.add(new AuthorizationModule(settings));
|
||||
if (enabled == false || auditingEnabled(settings) == false) {
|
||||
modules.add(b -> {
|
||||
b.bind(AuditTrailService.class).toProvider(Providers.of(null));
|
||||
b.bind(AuditTrail.class).toInstance(AuditTrail.NOOP);
|
||||
});
|
||||
}
|
||||
if (enabled == false) {
|
||||
modules.add(b -> b.bind(CryptoService.class).toProvider(Providers.of(null)));
|
||||
modules.add(new SecurityModule(settings, securityLicenseState));
|
||||
modules.add(new AuditTrailModule(settings));
|
||||
modules.add(b -> {
|
||||
b.bind(CryptoService.class).toProvider(Providers.of(null));
|
||||
});
|
||||
modules.add(new SecurityModule(settings));
|
||||
modules.add(new SecurityTransportModule(settings));
|
||||
return modules;
|
||||
}
|
||||
@ -159,14 +216,20 @@ public class Security implements ActionPlugin {
|
||||
// we can't load that at construction time since the license plugin might not have been loaded at that point
|
||||
// which might not be the case during Plugin class instantiation. Once nodeModules are pulled
|
||||
// everything should have been loaded
|
||||
securityLicenseState = new SecurityLicenseState();
|
||||
modules.add(b -> b.bind(CryptoService.class).toInstance(cryptoService));
|
||||
modules.add(new SecurityModule(settings, securityLicenseState));
|
||||
modules.add(new AuditTrailModule(settings));
|
||||
modules.add(b -> {
|
||||
b.bind(CryptoService.class).toInstance(cryptoService);
|
||||
if (auditingEnabled(settings)) {
|
||||
b.bind(AuditTrail.class).to(AuditTrailService.class); // interface used by some actions...
|
||||
}
|
||||
if (indexAuditLoggingEnabled(settings) == false) {
|
||||
// TODO: remove this once we can construct SecurityLifecycleService without guice
|
||||
b.bind(IndexAuditTrail.class).toProvider(Providers.of(null));
|
||||
}
|
||||
});
|
||||
modules.add(new SecurityModule(settings));
|
||||
modules.add(new SecurityRestModule(settings));
|
||||
modules.add(new SecurityActionModule(settings));
|
||||
modules.add(new SecurityTransportModule(settings));
|
||||
modules.add(new SSLModule(settings));
|
||||
return modules;
|
||||
}
|
||||
|
||||
@ -175,17 +238,73 @@ public class Security implements ActionPlugin {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Class<? extends LifecycleComponent>> list = new ArrayList<>();
|
||||
|
||||
//TODO why only focus on file audit logs? shouldn't we just check if audit trail is enabled in general?
|
||||
if (AuditTrailModule.fileAuditLoggingEnabled(settings) == true) {
|
||||
list.add(LoggingAuditTrail.class);
|
||||
}
|
||||
list.add(SecurityLicensee.class);
|
||||
list.add(FileRolesStore.class);
|
||||
list.add(Realms.class);
|
||||
return list;
|
||||
}
|
||||
|
||||
public Collection<Object> createComponents(InternalClient client, ThreadPool threadPool, ClusterService clusterService,
|
||||
ResourceWatcherService resourceWatcherService, List<XPackExtension> extensions) {
|
||||
if (enabled == false) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Object> components = new ArrayList<>();
|
||||
|
||||
final SSLConfiguration.Global globalSslConfig = new SSLConfiguration.Global(settings);
|
||||
final ClientSSLService clientSSLService = new ClientSSLService(settings, env, globalSslConfig, resourceWatcherService);
|
||||
final ServerSSLService serverSSLService = new ServerSSLService(settings, env, globalSslConfig, resourceWatcherService);
|
||||
components.add(clientSSLService);
|
||||
components.add(serverSSLService);
|
||||
|
||||
// realms construction
|
||||
final NativeUsersStore nativeUsersStore = new NativeUsersStore(settings, client, threadPool);
|
||||
final ReservedRealm reservedRealm = new ReservedRealm(env, settings, nativeUsersStore);
|
||||
Map<String, Realm.Factory> realmFactories = new HashMap<>();
|
||||
realmFactories.put(FileRealm.TYPE, config -> new FileRealm(config, resourceWatcherService));
|
||||
realmFactories.put(NativeRealm.TYPE, config -> new NativeRealm(config, nativeUsersStore));
|
||||
realmFactories.put(ActiveDirectoryRealm.TYPE,
|
||||
config -> new ActiveDirectoryRealm(config, resourceWatcherService, clientSSLService));
|
||||
realmFactories.put(LdapRealm.TYPE, config -> new LdapRealm(config, resourceWatcherService, clientSSLService));
|
||||
realmFactories.put(PkiRealm.TYPE, config -> new PkiRealm(config, resourceWatcherService));
|
||||
for (XPackExtension extension : extensions) {
|
||||
Map<String, Realm.Factory> newRealms = extension.getRealms();
|
||||
for (Map.Entry<String, Realm.Factory> entry : newRealms.entrySet()) {
|
||||
if (realmFactories.put(entry.getKey(), entry.getValue()) != null) {
|
||||
throw new IllegalArgumentException("Realm type [" + entry.getKey() + "] is already registered");
|
||||
}
|
||||
}
|
||||
}
|
||||
final Realms realms = new Realms(settings, env, realmFactories, securityLicenseState, reservedRealm);
|
||||
components.add(nativeUsersStore);
|
||||
components.add(realms);
|
||||
|
||||
// audit trails construction
|
||||
if (AUDIT_ENABLED_SETTING.get(settings)) {
|
||||
List<String> outputs = AUDIT_OUTPUTS_SETTING.get(settings);
|
||||
if (outputs.isEmpty()) {
|
||||
throw new IllegalArgumentException("Audit logging is enabled but there are zero output types in "
|
||||
+ AUDIT_ENABLED_SETTING.getKey());
|
||||
}
|
||||
Set<AuditTrail> auditTrails = new LinkedHashSet<>();
|
||||
for (String output : outputs) {
|
||||
switch (output) {
|
||||
case LoggingAuditTrail.NAME:
|
||||
auditTrails.add(new LoggingAuditTrail(settings, clusterService, threadPool));
|
||||
break;
|
||||
case IndexAuditTrail.NAME:
|
||||
IndexAuditTrail indexAuditTrail = new IndexAuditTrail(settings, client, threadPool, clusterService);
|
||||
auditTrails.add(indexAuditTrail);
|
||||
components.add(indexAuditTrail); // SecurityLifecycleService needs this....
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown audit trail output [" + output + "]");
|
||||
}
|
||||
}
|
||||
components.add(new AuditTrailService(settings, auditTrails.stream().collect(Collectors.toList()), securityLicenseState));
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
public Settings additionalSettings() {
|
||||
if (enabled == false) {
|
||||
return Settings.EMPTY;
|
||||
@ -200,7 +319,7 @@ public class Security implements ActionPlugin {
|
||||
settingsBuilder.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME);
|
||||
settingsBuilder.put(NetworkModule.TRANSPORT_SERVICE_TYPE_KEY, Security.NAME);
|
||||
settingsBuilder.put(NetworkModule.HTTP_TYPE_SETTING.getKey(), Security.NAME);
|
||||
SecurityNettyHttpServerTransport.overrideSettings(settingsBuilder, settings);
|
||||
SecurityNetty3HttpServerTransport.overrideSettings(settingsBuilder, settings);
|
||||
addUserSettings(settings, settingsBuilder);
|
||||
addTribeSettings(settings, settingsBuilder);
|
||||
return settingsBuilder.build();
|
||||
@ -216,7 +335,7 @@ public class Security implements ActionPlugin {
|
||||
SSLConfiguration.Global.addSettings(settingsList);
|
||||
|
||||
// transport settings
|
||||
SecurityNettyTransport.addSettings(settingsList);
|
||||
SecurityNetty3Transport.addSettings(settingsList);
|
||||
|
||||
if (transportClientMode) {
|
||||
return settingsList;
|
||||
@ -229,7 +348,10 @@ public class Security implements ActionPlugin {
|
||||
IPFilter.addSettings(settingsList);
|
||||
|
||||
// audit settings
|
||||
AuditTrailModule.addSettings(settingsList);
|
||||
settingsList.add(AUDIT_ENABLED_SETTING);
|
||||
settingsList.add(AUDIT_OUTPUTS_SETTING);
|
||||
LoggingAuditTrail.registerSettings(settingsList);
|
||||
IndexAuditTrail.registerSettings(settingsList);
|
||||
|
||||
// authentication settings
|
||||
FileRolesStore.addSettings(settingsList);
|
||||
@ -241,7 +363,7 @@ public class Security implements ActionPlugin {
|
||||
InternalAuthorizationService.addSettings(settingsList);
|
||||
|
||||
// HTTP settings
|
||||
SecurityNettyHttpServerTransport.addSettings(settingsList);
|
||||
SecurityNetty3HttpServerTransport.addSettings(settingsList);
|
||||
|
||||
// encryption settings
|
||||
CryptoService.addSettings(settingsList);
|
||||
@ -339,20 +461,25 @@ public class Security implements ActionPlugin {
|
||||
RestChangePasswordAction.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Processor.Factory> getProcessors(Processor.Parameters parameters) {
|
||||
return Collections.singletonMap(SetSecurityUserProcessor.TYPE, new SetSecurityUserProcessor.Factory(parameters.threadContext));
|
||||
}
|
||||
|
||||
public void onModule(NetworkModule module) {
|
||||
|
||||
if (transportClientMode) {
|
||||
if (enabled) {
|
||||
module.registerTransport(Security.NAME, SecurityNettyTransport.class);
|
||||
module.registerTransport(Security.NAME, SecurityNetty3Transport.class);
|
||||
module.registerTransportService(Security.NAME, SecurityClientTransportService.class);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
module.registerTransport(Security.NAME, SecurityNettyTransport.class);
|
||||
module.registerTransport(Security.NAME, SecurityNetty3Transport.class);
|
||||
module.registerTransportService(Security.NAME, SecurityServerTransportService.class);
|
||||
module.registerHttpTransport(Security.NAME, SecurityNettyHttpServerTransport.class);
|
||||
module.registerHttpTransport(Security.NAME, SecurityNetty3HttpServerTransport.class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,13 +583,29 @@ public class Security implements ActionPlugin {
|
||||
return XPackPlugin.featureEnabledSetting("security." + feature);
|
||||
}
|
||||
|
||||
public static boolean auditingEnabled(Settings settings) {
|
||||
return AUDIT_ENABLED_SETTING.get(settings);
|
||||
}
|
||||
|
||||
public static boolean indexAuditLoggingEnabled(Settings settings) {
|
||||
if (auditingEnabled(settings)) {
|
||||
List<String> outputs = AUDIT_OUTPUTS_SETTING.get(settings);
|
||||
for (String output : outputs) {
|
||||
if (output.equals(IndexAuditTrail.NAME)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void validateAutoCreateIndex(Settings settings) {
|
||||
String value = settings.get("action.auto_create_index");
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean indexAuditingEnabled = AuditTrailModule.indexAuditLoggingEnabled(settings);
|
||||
final boolean indexAuditingEnabled = Security.indexAuditLoggingEnabled(settings);
|
||||
final String auditIndex = indexAuditingEnabled ? "," + IndexAuditTrail.INDEX_NAME_PREFIX + "*" : "";
|
||||
String errorMessage = LoggerMessageFormat.format("the [action.auto_create_index] setting value [{}] is too" +
|
||||
" restrictive. disable [action.auto_create_index] or set it to " +
|
||||
|
@ -21,8 +21,8 @@ import org.elasticsearch.xpack.XPackFeatureSet;
|
||||
import org.elasticsearch.xpack.security.authz.store.RolesStore;
|
||||
import org.elasticsearch.xpack.security.crypto.CryptoService;
|
||||
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
|
||||
import org.elasticsearch.xpack.security.transport.netty.SecurityNettyHttpServerTransport;
|
||||
import org.elasticsearch.xpack.security.transport.netty.SecurityNettyTransport;
|
||||
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3HttpServerTransport;
|
||||
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3Transport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -122,8 +122,8 @@ public class SecurityFeatureSet implements XPackFeatureSet {
|
||||
|
||||
static Map<String, Object> sslUsage(Settings settings) {
|
||||
Map<String, Object> map = new HashMap<>(2);
|
||||
map.put("http", Collections.singletonMap("enabled", SecurityNettyHttpServerTransport.SSL_SETTING.get(settings)));
|
||||
map.put("transport", Collections.singletonMap("enabled", SecurityNettyTransport.SSL_SETTING.get(settings)));
|
||||
map.put("http", Collections.singletonMap("enabled", SecurityNetty3HttpServerTransport.SSL_SETTING.get(settings)));
|
||||
map.put("transport", Collections.singletonMap("enabled", SecurityNetty3Transport.SSL_SETTING.get(settings)));
|
||||
return map;
|
||||
}
|
||||
|
||||
|
@ -5,28 +5,21 @@
|
||||
*/
|
||||
package org.elasticsearch.xpack.security;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent;
|
||||
import org.elasticsearch.license.plugin.core.Licensee;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SecurityLicensee extends AbstractLicenseeComponent<SecurityLicensee> implements Licensee {
|
||||
public class SecurityLicensee extends AbstractLicenseeComponent {
|
||||
|
||||
private final boolean isTribeNode;
|
||||
private final SecurityLicenseState securityLicenseState;
|
||||
|
||||
@Inject
|
||||
public SecurityLicensee(Settings settings, LicenseeRegistry clientService, SecurityLicenseState securityLicenseState) {
|
||||
super(settings, Security.NAME, clientService);
|
||||
public SecurityLicensee(Settings settings, SecurityLicenseState securityLicenseState) {
|
||||
super(settings, Security.NAME);
|
||||
this.securityLicenseState = securityLicenseState;
|
||||
this.isTribeNode = settings.getGroups("tribe", true).isEmpty() == false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -44,66 +37,50 @@ public class SecurityLicensee extends AbstractLicenseeComponent<SecurityLicensee
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] acknowledgmentMessages(License currentLicense, License newLicense) {
|
||||
switch (newLicense.operationMode()) {
|
||||
public String[] acknowledgmentMessages(License.OperationMode currentMode, License.OperationMode newMode) {
|
||||
switch (newMode) {
|
||||
case BASIC:
|
||||
if (currentLicense != null) {
|
||||
switch (currentLicense.operationMode()) {
|
||||
case TRIAL:
|
||||
case STANDARD:
|
||||
case GOLD:
|
||||
case PLATINUM:
|
||||
return new String[] {
|
||||
"The following X-Pack security functionality will be disabled: authentication, authorization, " +
|
||||
"ip filtering, and auditing. Please restart your node after applying the license.",
|
||||
"Field and document level access control will be disabled.",
|
||||
"Custom realms will be ignored."
|
||||
};
|
||||
}
|
||||
switch (currentMode) {
|
||||
case TRIAL:
|
||||
case STANDARD:
|
||||
case GOLD:
|
||||
case PLATINUM:
|
||||
return new String[] {
|
||||
"The following X-Pack security functionality will be disabled: authentication, authorization, " +
|
||||
"ip filtering, and auditing. Please restart your node after applying the license.",
|
||||
"Field and document level access control will be disabled.",
|
||||
"Custom realms will be ignored."
|
||||
};
|
||||
}
|
||||
break;
|
||||
case GOLD:
|
||||
if (currentLicense != null) {
|
||||
switch (currentLicense.operationMode()) {
|
||||
case BASIC:
|
||||
case STANDARD:
|
||||
// ^^ though technically it was already disabled, it's not bad to remind them
|
||||
case TRIAL:
|
||||
case PLATINUM:
|
||||
return new String[] {
|
||||
"Field and document level access control will be disabled.",
|
||||
"Custom realms will be ignored."
|
||||
};
|
||||
}
|
||||
switch (currentMode) {
|
||||
case BASIC:
|
||||
case STANDARD:
|
||||
// ^^ though technically it was already disabled, it's not bad to remind them
|
||||
case TRIAL:
|
||||
case PLATINUM:
|
||||
return new String[] {
|
||||
"Field and document level access control will be disabled.",
|
||||
"Custom realms will be ignored."
|
||||
};
|
||||
}
|
||||
break;
|
||||
case STANDARD:
|
||||
if (currentLicense != null) {
|
||||
switch (currentLicense.operationMode()) {
|
||||
case BASIC:
|
||||
// ^^ though technically it was already disabled, it's not bad to remind them
|
||||
case GOLD:
|
||||
case PLATINUM:
|
||||
case TRIAL:
|
||||
return new String[] {
|
||||
"Authentication will be limited to the native realms.",
|
||||
"IP filtering and auditing will be disabled.",
|
||||
"Field and document level access control will be disabled.",
|
||||
"Custom realms will be ignored."
|
||||
};
|
||||
}
|
||||
switch (currentMode) {
|
||||
case BASIC:
|
||||
// ^^ though technically it was already disabled, it's not bad to remind them
|
||||
case GOLD:
|
||||
case PLATINUM:
|
||||
case TRIAL:
|
||||
return new String[] {
|
||||
"Authentication will be limited to the native realms.",
|
||||
"IP filtering and auditing will be disabled.",
|
||||
"Field and document level access control will be disabled.",
|
||||
"Custom realms will be ignored."
|
||||
};
|
||||
}
|
||||
}
|
||||
return Strings.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() throws ElasticsearchException {
|
||||
// we rely on the initial licensee state to be enabled with trial operation mode
|
||||
// to ensure no operation is blocked due to not registering the licensee on a
|
||||
// tribe node
|
||||
if (isTribeNode == false) {
|
||||
super.doStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,9 @@ import org.elasticsearch.cluster.ClusterStateListener;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.component.LifecycleListener;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.Provider;
|
||||
import org.elasticsearch.common.inject.internal.Nullable;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailModule;
|
||||
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
|
||||
import org.elasticsearch.xpack.security.authz.store.NativeRolesStore;
|
||||
@ -41,8 +40,8 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
|
||||
|
||||
@Inject
|
||||
public SecurityLifecycleService(Settings settings, ClusterService clusterService, ThreadPool threadPool,
|
||||
IndexAuditTrail indexAuditTrail, NativeUsersStore nativeUserStore,
|
||||
NativeRolesStore nativeRolesStore, Provider<InternalClient> clientProvider) {
|
||||
@Nullable IndexAuditTrail indexAuditTrail, NativeUsersStore nativeUserStore,
|
||||
NativeRolesStore nativeRolesStore, InternalClient client) {
|
||||
super(settings);
|
||||
this.settings = settings;
|
||||
this.threadPool = threadPool;
|
||||
@ -54,7 +53,7 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
|
||||
clusterService.add(this);
|
||||
clusterService.add(nativeUserStore);
|
||||
clusterService.add(nativeRolesStore);
|
||||
clusterService.add(new SecurityTemplateService(settings, clusterService, clientProvider, threadPool));
|
||||
clusterService.add(new SecurityTemplateService(settings, clusterService, client, threadPool));
|
||||
clusterService.addLifecycleListener(new LifecycleListener() {
|
||||
|
||||
@Override
|
||||
@ -111,7 +110,7 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
|
||||
}
|
||||
|
||||
try {
|
||||
if (AuditTrailModule.indexAuditLoggingEnabled(settings) &&
|
||||
if (Security.indexAuditLoggingEnabled(settings) &&
|
||||
indexAuditTrail.state() == IndexAuditTrail.State.INITIALIZED) {
|
||||
if (indexAuditTrail.canStart(event, master)) {
|
||||
threadPool.generic().execute(new AbstractRunnable() {
|
||||
@ -146,19 +145,23 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to stop native roles module", e);
|
||||
}
|
||||
try {
|
||||
indexAuditTrail.stop();
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to stop audit trail module", e);
|
||||
if (indexAuditTrail != null) {
|
||||
try {
|
||||
indexAuditTrail.stop();
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to stop audit trail module", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
// There is no .close() method for the roles module
|
||||
try {
|
||||
indexAuditTrail.close();
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to close audit trail module", e);
|
||||
if (indexAuditTrail != null) {
|
||||
try {
|
||||
indexAuditTrail.close();
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to close audit trail module", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,21 +5,17 @@
|
||||
*/
|
||||
package org.elasticsearch.xpack.security;
|
||||
|
||||
import org.elasticsearch.common.inject.util.Providers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.xpack.security.support.AbstractSecurityModule;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.security.support.AbstractSecurityModule;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SecurityModule extends AbstractSecurityModule {
|
||||
|
||||
private final SecurityLicenseState securityLicenseState;
|
||||
|
||||
public SecurityModule(Settings settings, SecurityLicenseState securityLicenseState) {
|
||||
public SecurityModule(Settings settings) {
|
||||
super(settings);
|
||||
this.securityLicenseState = securityLicenseState;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -28,24 +24,14 @@ public class SecurityModule extends AbstractSecurityModule {
|
||||
return;
|
||||
}
|
||||
|
||||
if (securityLicenseState != null) {
|
||||
bind(SecurityLicenseState.class).toInstance(securityLicenseState);
|
||||
} else {
|
||||
bind(SecurityLicenseState.class).toProvider(Providers.<SecurityLicenseState>of(null));
|
||||
}
|
||||
|
||||
XPackPlugin.bindFeatureSet(binder(), SecurityFeatureSet.class);
|
||||
|
||||
if (securityEnabled) {
|
||||
bind(SecurityContext.Secure.class).asEagerSingleton();
|
||||
bind(SecurityContext.class).to(SecurityContext.Secure.class);
|
||||
bind(SecurityLifecycleService.class).asEagerSingleton();
|
||||
bind(InternalClient.Secure.class).asEagerSingleton();
|
||||
bind(InternalClient.class).to(InternalClient.Secure.class);
|
||||
} else {
|
||||
bind(SecurityContext.class).toInstance(SecurityContext.Insecure.INSTANCE);
|
||||
bind(InternalClient.Insecure.class).asEagerSingleton();
|
||||
bind(InternalClient.class).to(InternalClient.Insecure.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,19 +37,18 @@ public class SecurityTemplateService extends AbstractComponent implements Cluste
|
||||
public static final String SECURITY_TEMPLATE_NAME = "security-index-template";
|
||||
|
||||
private final ThreadPool threadPool;
|
||||
private final Provider<InternalClient> clientProvider;
|
||||
private final InternalClient client;
|
||||
private final AtomicBoolean templateCreationPending = new AtomicBoolean(false);
|
||||
|
||||
public SecurityTemplateService(Settings settings, ClusterService clusterService,
|
||||
Provider<InternalClient> clientProvider, ThreadPool threadPool) {
|
||||
InternalClient client, ThreadPool threadPool) {
|
||||
super(settings);
|
||||
this.threadPool = threadPool;
|
||||
this.clientProvider = clientProvider;
|
||||
this.client = client;
|
||||
clusterService.add(this);
|
||||
}
|
||||
|
||||
private void createSecurityTemplate() {
|
||||
final Client client = clientProvider.get();
|
||||
try (InputStream is = getClass().getResourceAsStream("/" + SECURITY_TEMPLATE_NAME + ".json")) {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
Streams.copy(is, out);
|
||||
@ -83,7 +82,8 @@ public class SecurityTemplateService extends AbstractComponent implements Cluste
|
||||
if (securityIndexRouting == null) {
|
||||
if (event.localNodeMaster()) {
|
||||
ClusterState state = event.state();
|
||||
// TODO for the future need to add some checking in the event the template needs to be updated...
|
||||
// norelease we need to add some checking in the event the template needs to be updated and also the mappings need to be
|
||||
// updated on index too!
|
||||
IndexTemplateMetaData templateMeta = state.metaData().templates().get(SECURITY_TEMPLATE_NAME);
|
||||
final boolean createTemplate = (templateMeta == null);
|
||||
|
||||
|
@ -8,18 +8,19 @@ package org.elasticsearch.xpack.security.action.role;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.support.WriteRequest;
|
||||
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.xpack.security.authz.RoleDescriptor;
|
||||
import org.elasticsearch.xpack.security.support.MetadataUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.action.ValidateActions.addValidationError;
|
||||
|
||||
@ -33,6 +34,7 @@ public class PutRoleRequest extends ActionRequest<PutRoleRequest> implements Wri
|
||||
private List<RoleDescriptor.IndicesPrivileges> indicesPrivileges = new ArrayList<>();
|
||||
private String[] runAs = Strings.EMPTY_ARRAY;
|
||||
private RefreshPolicy refreshPolicy = RefreshPolicy.IMMEDIATE;
|
||||
private Map<String, Object> metadata;
|
||||
|
||||
public PutRoleRequest() {
|
||||
}
|
||||
@ -43,6 +45,10 @@ public class PutRoleRequest extends ActionRequest<PutRoleRequest> implements Wri
|
||||
if (name == null) {
|
||||
validationException = addValidationError("role name is missing", validationException);
|
||||
}
|
||||
if (metadata != null && MetadataUtils.containsReservedMetadata(metadata)) {
|
||||
validationException =
|
||||
addValidationError("metadata keys may not start with [" + MetadataUtils.RESERVED_PREFIX + "]", validationException);
|
||||
}
|
||||
return validationException;
|
||||
}
|
||||
|
||||
@ -86,6 +92,10 @@ public class PutRoleRequest extends ActionRequest<PutRoleRequest> implements Wri
|
||||
return refreshPolicy;
|
||||
}
|
||||
|
||||
public void metadata(Map<String, Object> metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
@ -102,6 +112,10 @@ public class PutRoleRequest extends ActionRequest<PutRoleRequest> implements Wri
|
||||
return runAs;
|
||||
}
|
||||
|
||||
public Map<String, Object> metadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
@ -114,6 +128,7 @@ public class PutRoleRequest extends ActionRequest<PutRoleRequest> implements Wri
|
||||
}
|
||||
runAs = in.readStringArray();
|
||||
refreshPolicy = RefreshPolicy.readFrom(in);
|
||||
metadata = in.readMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -127,12 +142,14 @@ public class PutRoleRequest extends ActionRequest<PutRoleRequest> implements Wri
|
||||
}
|
||||
out.writeStringArray(runAs);
|
||||
refreshPolicy.writeTo(out);
|
||||
out.writeMap(metadata);
|
||||
}
|
||||
|
||||
RoleDescriptor roleDescriptor() {
|
||||
return new RoleDescriptor(name,
|
||||
clusterPrivileges,
|
||||
indicesPrivileges.toArray(new RoleDescriptor.IndicesPrivileges[indicesPrivileges.size()]),
|
||||
runAs);
|
||||
runAs,
|
||||
metadata);
|
||||
}
|
||||
}
|
@ -12,6 +12,8 @@ import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.xpack.security.authz.RoleDescriptor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Builder for requests to add a role to the administrative index
|
||||
*/
|
||||
@ -33,6 +35,7 @@ public class PutRoleRequestBuilder extends ActionRequestBuilder<PutRoleRequest,
|
||||
request.cluster(descriptor.getClusterPrivileges());
|
||||
request.addIndex(descriptor.getIndicesPrivileges());
|
||||
request.runAs(descriptor.getRunAs());
|
||||
request.metadata(descriptor.getMetadata());
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -56,4 +59,9 @@ public class PutRoleRequestBuilder extends ActionRequestBuilder<PutRoleRequest,
|
||||
request.addIndex(indices, privileges, fields, query);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PutRoleRequestBuilder metadata(Map<String, Object> metadata) {
|
||||
request.metadata(metadata);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user