-
Notifications
You must be signed in to change notification settings - Fork 25.3k
Introduce system index APIs for Kibana #52385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9e8c213
80c8c76
8cb8a65
39b6290
3d80bd3
758409c
4577616
46325b2
b0194a8
86a27ce
16e5e87
d9fa9ae
15aad51
2dabec8
43e735e
3bf05f1
2a74996
2a8b637
863fe79
b1c53f7
eaac89d
43d4134
954bcad
5778129
52b609d
681924e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* Licensed to Elasticsearch under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
esplugin { | ||
description 'Plugin exposing APIs for Kibana system indices' | ||
classname 'org.elasticsearch.kibana.KibanaPlugin' | ||
} | ||
|
||
dependencies { | ||
compile project(path: ':modules:reindex', configuration: 'runtime') | ||
} | ||
|
||
testClusters.integTest { | ||
module file(project(':modules:reindex').tasks.bundlePlugin.archiveFile) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/* | ||
* Licensed to Elasticsearch under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
package org.elasticsearch.kibana; | ||
|
||
import org.elasticsearch.client.node.NodeClient; | ||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; | ||
import org.elasticsearch.cluster.node.DiscoveryNodes; | ||
import org.elasticsearch.common.settings.ClusterSettings; | ||
import org.elasticsearch.common.settings.IndexScopedSettings; | ||
import org.elasticsearch.common.settings.Setting; | ||
import org.elasticsearch.common.settings.Setting.Property; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.common.settings.SettingsFilter; | ||
import org.elasticsearch.index.reindex.RestDeleteByQueryAction; | ||
import org.elasticsearch.indices.SystemIndexDescriptor; | ||
import org.elasticsearch.plugins.Plugin; | ||
import org.elasticsearch.plugins.SystemIndexPlugin; | ||
import org.elasticsearch.rest.BaseRestHandler; | ||
import org.elasticsearch.rest.RestController; | ||
import org.elasticsearch.rest.RestHandler; | ||
import org.elasticsearch.rest.RestRequest; | ||
import org.elasticsearch.rest.action.admin.indices.RestCreateIndexAction; | ||
import org.elasticsearch.rest.action.admin.indices.RestGetAliasesAction; | ||
import org.elasticsearch.rest.action.admin.indices.RestGetIndicesAction; | ||
import org.elasticsearch.rest.action.admin.indices.RestIndexPutAliasAction; | ||
import org.elasticsearch.rest.action.admin.indices.RestRefreshAction; | ||
import org.elasticsearch.rest.action.admin.indices.RestUpdateSettingsAction; | ||
import org.elasticsearch.rest.action.document.RestBulkAction; | ||
import org.elasticsearch.rest.action.document.RestDeleteAction; | ||
import org.elasticsearch.rest.action.document.RestGetAction; | ||
import org.elasticsearch.rest.action.document.RestIndexAction; | ||
import org.elasticsearch.rest.action.document.RestIndexAction.AutoIdHandler; | ||
import org.elasticsearch.rest.action.document.RestIndexAction.CreateHandler; | ||
import org.elasticsearch.rest.action.document.RestMultiGetAction; | ||
import org.elasticsearch.rest.action.document.RestUpdateAction; | ||
import org.elasticsearch.rest.action.search.RestClearScrollAction; | ||
import org.elasticsearch.rest.action.search.RestSearchAction; | ||
import org.elasticsearch.rest.action.search.RestSearchScrollAction; | ||
|
||
import java.io.IOException; | ||
import java.util.Collection; | ||
import java.util.List; | ||
import java.util.function.Function; | ||
import java.util.function.Supplier; | ||
import java.util.stream.Collectors; | ||
|
||
public class KibanaPlugin extends Plugin implements SystemIndexPlugin { | ||
|
||
public static final Setting<List<String>> KIBANA_INDEX_NAMES_SETTING = Setting.listSetting("kibana.system_indices", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tylersmalley I was looking at elastic/kibana#49764 and I wanted to make sure I understood the request there for the paths where you have Right now in this plugin, the setting I have would look like this in the kibana.system_indices: [ ".kibana", ".kibana_task_manager", ".reporting" ] I think the Kibana issue is actually looking for something more like: kibana:
instances:
my_kibana:
kibana_index: ".my-kibana"
task_manager_index: ".my-tm"
reporting_index: ".my-reports" Is this correct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The latter is correct. Ideally, I would like to define a list of names which we could derive each index off of, but that won't work today as users can configure them individually. In that example, would the endpoint be It would probably also make sense to include a default so Kibana instance configuration is only necessary if they intend on having multiple instances. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes that would be the endpoint path. For the default, I think we will still want an instance name so maybe just ‘kibana’ for that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. Though, could we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the risk for not whitelisting kibana instances and indices? From a user's perspective it's error prone to have to adjust both the kibana and elasticsearch config files and keep them in sync. The status quo is that Kibana creates any instances (it's currently just an index prefix) and indices it wants to. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Every system index plugin needs to declare the system indices it is used for as a way to identify indices that are system indices. If you are ok with just creating all of your indices under a single prefix, then I think that would be fine. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A question was also brought up as to if we would consider this a breaking change if it was introduced before 8.0. Currently, to migrate to the system indices the user would be required to update ES and Kibana configuration. The prefixing is interesting idea worth exploring, but would require coming up with a plan to migrate to these index names, correct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point on it being breaking. One thing we can do is allow the APIs under There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the time being, I have gone ahead and removed the limiting of indices accessible by the APIs until we figure out what we should do here regarding these indices and their names. |
||
List.of(".kibana*", ".reporting"), Function.identity(), Property.NodeScope); | ||
|
||
@Override | ||
public Collection<SystemIndexDescriptor> getSystemIndexDescriptors(Settings settings) { | ||
return KIBANA_INDEX_NAMES_SETTING.get(settings).stream() | ||
.map(pattern -> new SystemIndexDescriptor(pattern, "System index used by kibana")) | ||
.collect(Collectors.toUnmodifiableList()); | ||
} | ||
|
||
@Override | ||
public List<RestHandler> getRestHandlers(Settings settings, RestController restController, ClusterSettings clusterSettings, | ||
IndexScopedSettings indexScopedSettings, SettingsFilter settingsFilter, | ||
IndexNameExpressionResolver indexNameExpressionResolver, | ||
Supplier<DiscoveryNodes> nodesInCluster) { | ||
// TODO need to figure out what subset of system indices Kibana should have access to via these APIs | ||
final List<String> allowedIndexPatterns = List.of(); | ||
return List.of( | ||
// Based on https://github.com/elastic/kibana/issues/49764 | ||
// apis needed to perform migrations... ideally these will go away | ||
new KibanaWrappedRestHandler(new RestCreateIndexAction(), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestGetAliasesAction(), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestIndexPutAliasAction(), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestRefreshAction(), allowedIndexPatterns), | ||
|
||
// apis needed to access saved objects | ||
new KibanaWrappedRestHandler(new RestGetAction(), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestMultiGetAction(settings), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestSearchAction(), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestBulkAction(settings), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestDeleteAction(), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestDeleteByQueryAction(), allowedIndexPatterns), | ||
|
||
// api used for testing | ||
new KibanaWrappedRestHandler(new RestUpdateSettingsAction(), allowedIndexPatterns), | ||
|
||
// apis used specifically by reporting | ||
new KibanaWrappedRestHandler(new RestGetIndicesAction(), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestIndexAction(), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new CreateHandler(), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new AutoIdHandler(nodesInCluster), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestUpdateAction(), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestSearchScrollAction(), allowedIndexPatterns), | ||
new KibanaWrappedRestHandler(new RestClearScrollAction(), allowedIndexPatterns) | ||
); | ||
|
||
} | ||
|
||
@Override | ||
public List<Setting<?>> getSettings() { | ||
return List.of(KIBANA_INDEX_NAMES_SETTING); | ||
} | ||
|
||
static class KibanaWrappedRestHandler extends BaseRestHandler.Wrapper { | ||
|
||
private final List<String> allowedIndexPatterns; | ||
|
||
KibanaWrappedRestHandler(BaseRestHandler delegate, List<String> allowedIndexPatterns) { | ||
super(delegate); | ||
this.allowedIndexPatterns = allowedIndexPatterns; | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return "kibana_" + super.getName(); | ||
} | ||
|
||
@Override | ||
public List<Route> routes() { | ||
return super.routes().stream().map(route -> new Route(route.getMethod(), "/_kibana" + route.getPath())) | ||
.collect(Collectors.toUnmodifiableList()); | ||
} | ||
|
||
@Override | ||
protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { | ||
client.threadPool().getThreadContext().allowSystemIndexAccess(allowedIndexPatterns); | ||
return super.prepareRequest(request, client); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
|
||
/* | ||
* Licensed to Elasticsearch under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
package org.elasticsearch.kibana; | ||
|
||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.indices.SystemIndexDescriptor; | ||
import org.elasticsearch.test.ESTestCase; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
import static org.hamcrest.Matchers.contains; | ||
import static org.hamcrest.Matchers.is; | ||
|
||
public class KibanaPluginTests extends ESTestCase { | ||
|
||
public void testKibanaIndexNames() { | ||
assertThat(new KibanaPlugin().getSettings(), contains(KibanaPlugin.KIBANA_INDEX_NAMES_SETTING)); | ||
assertThat(new KibanaPlugin().getSystemIndexDescriptors(Settings.EMPTY).stream() | ||
.map(SystemIndexDescriptor::getIndexPattern).collect(Collectors.toUnmodifiableList()), | ||
contains(".kibana*", ".reporting")); | ||
final List<String> names = List.of("." + randomAlphaOfLength(4), "." + randomAlphaOfLength(6)); | ||
final List<String> namesFromDescriptors = new KibanaPlugin().getSystemIndexDescriptors( | ||
Settings.builder().putList(KibanaPlugin.KIBANA_INDEX_NAMES_SETTING.getKey(), names).build() | ||
).stream().map(SystemIndexDescriptor::getIndexPattern).collect(Collectors.toUnmodifiableList()); | ||
assertThat(namesFromDescriptors, is(names)); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.