From 5c0a7731530361bec661ffb1b4821ad92fc29576 Mon Sep 17 00:00:00 2001 From: Jay Modi Date: Wed, 7 Apr 2021 09:42:33 -0600 Subject: [PATCH] Manage Fleet system indices within Elasticsearch (#71413) This commit moves the management of seven system indices that are used by Fleet to an Elasticsearch plugin. The mappings were taken largely untouched from the Fleet server project, with the exception of adding a _meta field with a version key to enable the system indices infrastructure to manage these indices. Co-authored-by: Aleksandr Maus Backport of #70689 --- .../indices/SystemIndexManager.java | 3 + .../xpack/core/ClientHelper.java | 1 + .../src/main/resources/fleet-actions.json | 40 +++ .../core/src/main/resources/fleet-agents.json | 231 ++++++++++++++++++ .../src/main/resources/fleet-artifacts.json | 55 +++++ .../resources/fleet-enrollment-api-keys.json | 39 +++ .../main/resources/fleet-policies-leader.json | 28 +++ .../src/main/resources/fleet-policies.json | 34 +++ .../src/main/resources/fleet-servers.json | 54 ++++ x-pack/plugin/fleet/build.gradle | 11 +- .../xpack/fleet/FleetSystemIndicesIT.java | 174 +++++++++++++ .../org/elasticsearch/xpack/fleet/Fleet.java | 157 +++++++++++- .../elasticsearch/xpack/fleet/FleetTests.java | 10 +- .../security/authz/AuthorizationUtils.java | 2 + 14 files changed, 828 insertions(+), 11 deletions(-) create mode 100644 x-pack/plugin/core/src/main/resources/fleet-actions.json create mode 100644 x-pack/plugin/core/src/main/resources/fleet-agents.json create mode 100644 x-pack/plugin/core/src/main/resources/fleet-artifacts.json create mode 100644 x-pack/plugin/core/src/main/resources/fleet-enrollment-api-keys.json create mode 100644 x-pack/plugin/core/src/main/resources/fleet-policies-leader.json create mode 100644 x-pack/plugin/core/src/main/resources/fleet-policies.json create mode 100644 x-pack/plugin/core/src/main/resources/fleet-servers.json create mode 100644 x-pack/plugin/fleet/src/javaRestTest/java/org/elasticsearch/xpack/fleet/FleetSystemIndicesIT.java diff --git a/server/src/main/java/org/elasticsearch/indices/SystemIndexManager.java b/server/src/main/java/org/elasticsearch/indices/SystemIndexManager.java index ae3b32b584ff8..17d66778533aa 100644 --- a/server/src/main/java/org/elasticsearch/indices/SystemIndexManager.java +++ b/server/src/main/java/org/elasticsearch/indices/SystemIndexManager.java @@ -279,6 +279,9 @@ private Version readMappingVersion(SystemIndexDescriptor descriptor, MappingMeta } catch (ElasticsearchParseException e) { logger.error(new ParameterizedMessage("Cannot parse the mapping for index [{}]", indexName), e); throw new ElasticsearchException("Cannot parse the mapping for index [{}]", e, indexName); + } catch (IllegalArgumentException e) { + logger.error(new ParameterizedMessage("Cannot parse the mapping for index [{}]", indexName), e); + throw e; } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ClientHelper.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ClientHelper.java index 9111b64b1be74..e7b3c43f32803 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ClientHelper.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ClientHelper.java @@ -95,6 +95,7 @@ public static Map filterSecurityHeaders(Map head public static final String STACK_ORIGIN = "stack"; public static final String SEARCHABLE_SNAPSHOTS_ORIGIN = "searchable_snapshots"; public static final String LOGSTASH_MANAGEMENT_ORIGIN = "logstash_management"; + public static final String FLEET_ORIGIN = "fleet"; private ClientHelper() {} diff --git a/x-pack/plugin/core/src/main/resources/fleet-actions.json b/x-pack/plugin/core/src/main/resources/fleet-actions.json new file mode 100644 index 0000000000000..5fb5f6e13dfb4 --- /dev/null +++ b/x-pack/plugin/core/src/main/resources/fleet-actions.json @@ -0,0 +1,40 @@ +{ + "settings": { + "auto_expand_replicas": "0-1" + }, + "mappings": { + "_doc" : { + "dynamic": false, + "_meta": { + "version": "${fleet.version}" + }, + "properties": { + "action_id": { + "type": "keyword" + }, + "agents": { + "type": "keyword" + }, + "data": { + "enabled": false, + "type": "object" + }, + "expiration": { + "type": "date" + }, + "input_type": { + "type": "keyword" + }, + "@timestamp": { + "type": "date" + }, + "type": { + "type": "keyword" + }, + "user_id" : { + "type": "keyword" + } + } + } + } +} diff --git a/x-pack/plugin/core/src/main/resources/fleet-agents.json b/x-pack/plugin/core/src/main/resources/fleet-agents.json new file mode 100644 index 0000000000000..d77b4aaa71fcf --- /dev/null +++ b/x-pack/plugin/core/src/main/resources/fleet-agents.json @@ -0,0 +1,231 @@ +{ + "settings": { + "auto_expand_replicas": "0-1" + }, + "mappings": { + "_doc" : { + "dynamic": false, + "_meta": { + "version": "${fleet.version}" + }, + "properties": { + "access_api_key_id": { + "type": "keyword" + }, + "action_seq_no": { + "type": "integer", + "index": false + }, + "active": { + "type": "boolean" + }, + "agent": { + "properties": { + "id": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "default_api_key": { + "type": "keyword" + }, + "default_api_key_id": { + "type": "keyword" + }, + "enrolled_at": { + "type": "date" + }, + "last_checkin": { + "type": "date" + }, + "last_checkin_status": { + "type": "keyword" + }, + "last_updated": { + "type": "date" + }, + "local_metadata": { + "properties": { + "elastic": { + "properties": { + "agent": { + "properties": { + "build": { + "properties": { + "original": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "id": { + "type": "keyword" + }, + "log_level": { + "type": "keyword" + }, + "snapshot": { + "type": "boolean" + }, + "upgradeable": { + "type": "boolean" + }, + "version": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 16 + } + } + } + } + } + } + }, + "host": { + "properties": { + "architecture": { + "type": "keyword" + }, + "hostname": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "keyword" + }, + "ip": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 64 + } + } + }, + "mac": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 17 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "os": { + "properties": { + "family": { + "type": "keyword" + }, + "full": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 128 + } + } + }, + "kernel": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 128 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "platform": { + "type": "keyword" + }, + "version": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 32 + } + } + } + } + } + } + }, + "packages": { + "type": "keyword" + }, + "policy_coordinator_idx": { + "type": "integer" + }, + "policy_id": { + "type": "keyword" + }, + "policy_output_permissions_hash": { + "type": "keyword" + }, + "policy_revision_idx": { + "type": "integer" + }, + "shared_id": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "unenrolled_at": { + "type": "date" + }, + "unenrollment_started_at": { + "type": "date" + }, + "updated_at": { + "type": "date" + }, + "upgrade_started_at": { + "type": "date" + }, + "upgraded_at": { + "type": "date" + }, + "user_provided_metadata": { + "type": "object", + "enabled": false + } + } + } + } +} diff --git a/x-pack/plugin/core/src/main/resources/fleet-artifacts.json b/x-pack/plugin/core/src/main/resources/fleet-artifacts.json new file mode 100644 index 0000000000000..bb7fbda297db2 --- /dev/null +++ b/x-pack/plugin/core/src/main/resources/fleet-artifacts.json @@ -0,0 +1,55 @@ +{ + "settings": { + "auto_expand_replicas": "0-1" + }, + "mappings": { + "_doc" : { + "dynamic": false, + "_meta": { + "version": "${fleet.version}" + }, + "properties": { + "identifier": { + "type": "keyword" + }, + "compression_algorithm": { + "type": "keyword", + "index": false + }, + "encryption_algorithm": { + "type": "keyword", + "index": false + }, + "encoded_sha256": { + "type": "keyword" + }, + "encoded_size": { + "type": "long", + "index": false + }, + "decoded_sha256": { + "type": "keyword" + }, + "decoded_size": { + "type": "long", + "index": false + }, + "created": { + "type": "date" + }, + "package_name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "relative_url": { + "type": "keyword" + }, + "body": { + "type": "binary" + } + } + } + } +} diff --git a/x-pack/plugin/core/src/main/resources/fleet-enrollment-api-keys.json b/x-pack/plugin/core/src/main/resources/fleet-enrollment-api-keys.json new file mode 100644 index 0000000000000..2032bee4aaabb --- /dev/null +++ b/x-pack/plugin/core/src/main/resources/fleet-enrollment-api-keys.json @@ -0,0 +1,39 @@ +{ + "settings": { + "auto_expand_replicas": "0-1" + }, + "mappings": { + "_doc" : { + "dynamic": false, + "_meta": { + "version": "${fleet.version}" + }, + "properties": { + "active": { + "type": "boolean" + }, + "api_key": { + "type": "keyword" + }, + "api_key_id": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "expire_at": { + "type": "date" + }, + "name": { + "type": "keyword" + }, + "policy_id": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + } + } + } + } +} diff --git a/x-pack/plugin/core/src/main/resources/fleet-policies-leader.json b/x-pack/plugin/core/src/main/resources/fleet-policies-leader.json new file mode 100644 index 0000000000000..73179d529aae8 --- /dev/null +++ b/x-pack/plugin/core/src/main/resources/fleet-policies-leader.json @@ -0,0 +1,28 @@ +{ + "settings": { + "auto_expand_replicas": "0-1" + }, + "mappings": { + "_doc" : { + "dynamic": false, + "_meta": { + "version": "${fleet.version}" + }, + "properties": { + "server": { + "properties": { + "id": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "@timestamp": { + "type": "date" + } + } + } + } +} diff --git a/x-pack/plugin/core/src/main/resources/fleet-policies.json b/x-pack/plugin/core/src/main/resources/fleet-policies.json new file mode 100644 index 0000000000000..fac38befeba02 --- /dev/null +++ b/x-pack/plugin/core/src/main/resources/fleet-policies.json @@ -0,0 +1,34 @@ +{ + "settings": { + "auto_expand_replicas": "0-1" + }, + "mappings": { + "_doc" : { + "dynamic": false, + "_meta": { + "version": "${fleet.version}" + }, + "properties": { + "coordinator_idx": { + "type": "integer" + }, + "data": { + "enabled": false, + "type": "object" + }, + "default_fleet_server": { + "type": "boolean" + }, + "policy_id": { + "type": "keyword" + }, + "revision_idx": { + "type": "integer" + }, + "@timestamp": { + "type": "date" + } + } + } + } +} diff --git a/x-pack/plugin/core/src/main/resources/fleet-servers.json b/x-pack/plugin/core/src/main/resources/fleet-servers.json new file mode 100644 index 0000000000000..b9b9a8f5b5249 --- /dev/null +++ b/x-pack/plugin/core/src/main/resources/fleet-servers.json @@ -0,0 +1,54 @@ +{ + "settings": { + "auto_expand_replicas": "0-1" + }, + "mappings": { + "_doc" : { + "dynamic": false, + "_meta": { + "version": "${fleet.version}" + }, + "properties": { + "agent": { + "properties": { + "id": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "host": { + "properties": { + "architecture": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "ip": { + "type": "keyword" + }, + "name": { + "type": "keyword" + } + } + }, + "server": { + "properties": { + "id": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "@timestamp": { + "type": "date" + } + } + } + } +} diff --git a/x-pack/plugin/fleet/build.gradle b/x-pack/plugin/fleet/build.gradle index 7c68b82bf2a93..bc135af76077c 100644 --- a/x-pack/plugin/fleet/build.gradle +++ b/x-pack/plugin/fleet/build.gradle @@ -6,19 +6,22 @@ */ apply plugin: 'elasticsearch.esplugin' +apply plugin: 'elasticsearch.java-rest-test' esplugin { name 'x-pack-fleet' description 'Elasticsearch Expanded Pack Plugin - Plugin exposing APIs for Fleet system indices' classname 'org.elasticsearch.xpack.fleet.Fleet' + extendedPlugins = ['x-pack-core'] } dependencies { - api project(path: ':modules:reindex') + compileOnly project(path: xpackModule('core')) + testImplementation(testArtifact(project(xpackModule('core')))) + javaRestTestImplementation(project(path: xpackModule('core'))) + javaRestTestImplementation(testArtifact(project(xpackModule('core')))) } testClusters.all { - module ':modules:reindex' + testDistribution = 'DEFAULT' } - -addQaCheckDependencies() diff --git a/x-pack/plugin/fleet/src/javaRestTest/java/org/elasticsearch/xpack/fleet/FleetSystemIndicesIT.java b/x-pack/plugin/fleet/src/javaRestTest/java/org/elasticsearch/xpack/fleet/FleetSystemIndicesIT.java new file mode 100644 index 0000000000000..ea9fde1daca59 --- /dev/null +++ b/x-pack/plugin/fleet/src/javaRestTest/java/org/elasticsearch/xpack/fleet/FleetSystemIndicesIT.java @@ -0,0 +1,174 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* + * 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.xpack.fleet; + +import org.apache.http.util.EntityUtils; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.test.SecuritySettingsSourceField; +import org.elasticsearch.test.rest.ESRestTestCase; + +import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue; +import static org.hamcrest.Matchers.containsString; + +public class FleetSystemIndicesIT extends ESRestTestCase { + + static final String BASIC_AUTH_VALUE = basicAuthHeaderValue( + "x_pack_rest_user", + SecuritySettingsSourceField.TEST_PASSWORD_SECURE_STRING + ); + + @Override + protected Settings restClientSettings() { + return Settings.builder() + .put(ThreadContext.PREFIX + ".Authorization", BASIC_AUTH_VALUE) + .put(ThreadContext.PREFIX + ".X-elastic-product-origin", "fleet") + .build(); + } + + public void testSearchWithoutIndexCreatedIsAllowed() throws Exception { + Request request = new Request("GET", ".fleet-agents/_search"); + request.setJsonEntity("{ \"query\": { \"match_all\": {} } }"); + request.addParameter("ignore_unavailable", Boolean.TRUE.toString()); + + assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode()); + } + + public void testCreationOfFleetAgents() throws Exception { + Request request = new Request("PUT", ".fleet-agents"); + Response response = client().performRequest(request); + assertEquals(200, response.getStatusLine().getStatusCode()); + + request = new Request("GET", ".fleet-agents/_mapping"); + response = client().performRequest(request); + String responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("access_api_key_id")); + + request = new Request("GET", ".fleet-agents-7/_mapping"); + response = client().performRequest(request); + responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("access_api_key_id")); + } + + public void testCreationOfFleetActions() throws Exception { + Request request = new Request("PUT", ".fleet-actions"); + Response response = client().performRequest(request); + assertEquals(200, response.getStatusLine().getStatusCode()); + + request = new Request("GET", ".fleet-actions/_mapping"); + response = client().performRequest(request); + String responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("action_id")); + + request = new Request("GET", ".fleet-actions-7/_mapping"); + response = client().performRequest(request); + responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("action_id")); + } + + public void testCreationOfFleetArtifacts() throws Exception { + Request request = new Request("PUT", ".fleet-artifacts"); + Response response = client().performRequest(request); + assertEquals(200, response.getStatusLine().getStatusCode()); + + request = new Request("GET", ".fleet-artifacts/_mapping"); + response = client().performRequest(request); + String responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("encryption_algorithm")); + + request = new Request("GET", ".fleet-artifacts-7/_mapping"); + response = client().performRequest(request); + responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("encryption_algorithm")); + } + + public void testCreationOfFleetEnrollmentApiKeys() throws Exception { + Request request = new Request("PUT", ".fleet-enrollment-api-keys"); + Response response = client().performRequest(request); + assertEquals(200, response.getStatusLine().getStatusCode()); + + request = new Request("GET", ".fleet-enrollment-api-keys/_mapping"); + response = client().performRequest(request); + String responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("api_key_id")); + + request = new Request("GET", ".fleet-enrollment-api-keys-7/_mapping"); + response = client().performRequest(request); + responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("api_key_id")); + } + + public void testCreationOfFleetPolicies() throws Exception { + Request request = new Request("PUT", ".fleet-policies"); + Response response = client().performRequest(request); + assertEquals(200, response.getStatusLine().getStatusCode()); + + request = new Request("GET", ".fleet-policies/_mapping"); + response = client().performRequest(request); + String responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("coordinator_idx")); + + request = new Request("GET", ".fleet-policies-7/_mapping"); + response = client().performRequest(request); + responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("coordinator_idx")); + } + + public void testCreationOfFleetPoliciesLeader() throws Exception { + Request request = new Request("PUT", ".fleet-policies-leader"); + Response response = client().performRequest(request); + assertEquals(200, response.getStatusLine().getStatusCode()); + + request = new Request("GET", ".fleet-policies-leader/_mapping"); + response = client().performRequest(request); + String responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("server")); + + request = new Request("GET", ".fleet-policies-leader-7/_mapping"); + response = client().performRequest(request); + responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("server")); + } + + public void testCreationOfFleetServers() throws Exception { + Request request = new Request("PUT", ".fleet-servers"); + Response response = client().performRequest(request); + assertEquals(200, response.getStatusLine().getStatusCode()); + + request = new Request("GET", ".fleet-servers/_mapping"); + response = client().performRequest(request); + String responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("architecture")); + + request = new Request("GET", ".fleet-servers-7/_mapping"); + response = client().performRequest(request); + responseBody = EntityUtils.toString(response.getEntity()); + assertThat(responseBody, containsString("architecture")); + } +} diff --git a/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/Fleet.java b/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/Fleet.java index 2650d6b8e3939..35e5d1dfa4f42 100644 --- a/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/Fleet.java +++ b/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/Fleet.java @@ -7,16 +7,23 @@ package org.elasticsearch.xpack.fleet; +import org.elasticsearch.Version; +import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.indices.SystemIndexDescriptor; import org.elasticsearch.indices.SystemIndexDescriptor.Type; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.SystemIndexPlugin; +import org.elasticsearch.xpack.core.template.TemplateUtils; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; +import static org.elasticsearch.xpack.core.ClientHelper.FLEET_ORIGIN; + /** * A plugin to manage and provide access to the system indices used by Fleet. * @@ -24,15 +31,23 @@ */ public class Fleet extends Plugin implements SystemIndexPlugin { - private static final List ALLOWED_PRODUCTS = Arrays.asList("kibana", "fleet-server"); + private static final int CURRENT_INDEX_VERSION = 7; + private static final String VERSION_KEY = "version"; + private static final String MAPPING_VERSION_VARIABLE = "fleet.version"; + private static final List ALLOWED_PRODUCTS = Collections.unmodifiableList(Arrays.asList("kibana", "fleet")); @Override public Collection getSystemIndexDescriptors(Settings settings) { - return org.elasticsearch.common.collect.List.of( - new SystemIndexDescriptor(".fleet-servers*", "Configuration of fleet servers", Type.EXTERNAL_UNMANAGED, ALLOWED_PRODUCTS), - new SystemIndexDescriptor(".fleet-policies*", "Policies and enrollment keys", Type.EXTERNAL_UNMANAGED, ALLOWED_PRODUCTS), - new SystemIndexDescriptor(".fleet-agents*", "Agents and agent checkins", Type.EXTERNAL_UNMANAGED, ALLOWED_PRODUCTS), - new SystemIndexDescriptor(".fleet-actions*", "Fleet actions", Type.EXTERNAL_UNMANAGED, ALLOWED_PRODUCTS) + return Collections.unmodifiableList( + Arrays.asList( + fleetActionsSystemIndexDescriptor(), + fleetAgentsSystemIndexDescriptor(), + fleetEnrollmentApiKeysSystemIndexDescriptor(), + fleetPoliciesSystemIndexDescriptor(), + fleetPoliciesLeaderSystemIndexDescriptor(), + fleetServersSystemIndexDescriptors(), + fleetArtifactsSystemIndexDescriptors() + ) ); } @@ -45,4 +60,134 @@ public String getFeatureName() { public String getFeatureDescription() { return "Manages configuration for Fleet"; } + + private SystemIndexDescriptor fleetActionsSystemIndexDescriptor() { + PutIndexTemplateRequest request = new PutIndexTemplateRequest(); + request.source(loadTemplateSource("/fleet-actions.json"), XContentType.JSON); + + return SystemIndexDescriptor.builder() + .setType(Type.EXTERNAL_MANAGED) + .setAllowedElasticProductOrigins(ALLOWED_PRODUCTS) + .setOrigin(FLEET_ORIGIN) + .setVersionMetaKey(VERSION_KEY) + .setMappings(request.mappings().get("_doc")) + .setSettings(request.settings()) + .setPrimaryIndex(".fleet-actions-" + CURRENT_INDEX_VERSION) + .setIndexPattern(".fleet-actions*") + .setAliasName(".fleet-actions") + .setDescription("Fleet agents") + .build(); + } + + private SystemIndexDescriptor fleetAgentsSystemIndexDescriptor() { + PutIndexTemplateRequest request = new PutIndexTemplateRequest(); + request.source(loadTemplateSource("/fleet-agents.json"), XContentType.JSON); + + return SystemIndexDescriptor.builder() + .setType(Type.EXTERNAL_MANAGED) + .setAllowedElasticProductOrigins(ALLOWED_PRODUCTS) + .setOrigin(FLEET_ORIGIN) + .setVersionMetaKey(VERSION_KEY) + .setMappings(request.mappings().get("_doc")) + .setSettings(request.settings()) + .setPrimaryIndex(".fleet-agents-" + CURRENT_INDEX_VERSION) + .setIndexPattern(".fleet-agents*") + .setAliasName(".fleet-agents") + .setDescription("Configuration of fleet servers") + .build(); + } + + private SystemIndexDescriptor fleetEnrollmentApiKeysSystemIndexDescriptor() { + PutIndexTemplateRequest request = new PutIndexTemplateRequest(); + request.source(loadTemplateSource("/fleet-enrollment-api-keys.json"), XContentType.JSON); + + return SystemIndexDescriptor.builder() + .setType(Type.EXTERNAL_MANAGED) + .setAllowedElasticProductOrigins(ALLOWED_PRODUCTS) + .setOrigin(FLEET_ORIGIN) + .setVersionMetaKey(VERSION_KEY) + .setMappings(request.mappings().get("_doc")) + .setSettings(request.settings()) + .setPrimaryIndex(".fleet-enrollment-api-keys-" + CURRENT_INDEX_VERSION) + .setIndexPattern(".fleet-enrollment-api-keys*") + .setAliasName(".fleet-enrollment-api-keys") + .setDescription("Fleet API Keys for enrollment") + .build(); + } + + private SystemIndexDescriptor fleetPoliciesSystemIndexDescriptor() { + PutIndexTemplateRequest request = new PutIndexTemplateRequest(); + request.source(loadTemplateSource("/fleet-policies.json"), XContentType.JSON); + + return SystemIndexDescriptor.builder() + .setType(Type.EXTERNAL_MANAGED) + .setAllowedElasticProductOrigins(ALLOWED_PRODUCTS) + .setOrigin(FLEET_ORIGIN) + .setVersionMetaKey(VERSION_KEY) + .setMappings(request.mappings().get("_doc")) + .setSettings(request.settings()) + .setPrimaryIndex(".fleet-policies-" + CURRENT_INDEX_VERSION) + .setIndexPattern(".fleet-policies-[0-9]+*") + .setAliasName(".fleet-policies") + .setDescription("Fleet Policies") + .build(); + } + + private SystemIndexDescriptor fleetPoliciesLeaderSystemIndexDescriptor() { + PutIndexTemplateRequest request = new PutIndexTemplateRequest(); + request.source(loadTemplateSource("/fleet-policies-leader.json"), XContentType.JSON); + + return SystemIndexDescriptor.builder() + .setType(Type.EXTERNAL_MANAGED) + .setAllowedElasticProductOrigins(ALLOWED_PRODUCTS) + .setOrigin(FLEET_ORIGIN) + .setVersionMetaKey(VERSION_KEY) + .setMappings(request.mappings().get("_doc")) + .setSettings(request.settings()) + .setPrimaryIndex(".fleet-policies-leader-" + CURRENT_INDEX_VERSION) + .setIndexPattern(".fleet-policies-leader*") + .setAliasName(".fleet-policies-leader") + .setDescription("Fleet Policies leader") + .build(); + } + + private SystemIndexDescriptor fleetServersSystemIndexDescriptors() { + PutIndexTemplateRequest request = new PutIndexTemplateRequest(); + request.source(loadTemplateSource("/fleet-servers.json"), XContentType.JSON); + + return SystemIndexDescriptor.builder() + .setType(Type.EXTERNAL_MANAGED) + .setAllowedElasticProductOrigins(ALLOWED_PRODUCTS) + .setOrigin(FLEET_ORIGIN) + .setVersionMetaKey(VERSION_KEY) + .setMappings(request.mappings().get("_doc")) + .setSettings(request.settings()) + .setPrimaryIndex(".fleet-servers-" + CURRENT_INDEX_VERSION) + .setIndexPattern(".fleet-servers*") + .setAliasName(".fleet-servers") + .setDescription("Fleet servers") + .build(); + } + + private SystemIndexDescriptor fleetArtifactsSystemIndexDescriptors() { + PutIndexTemplateRequest request = new PutIndexTemplateRequest(); + request.source(loadTemplateSource("/fleet-artifacts.json"), XContentType.JSON); + + return SystemIndexDescriptor.builder() + .setType(Type.EXTERNAL_MANAGED) + .setAllowedElasticProductOrigins(ALLOWED_PRODUCTS) + .setOrigin(FLEET_ORIGIN) + .setVersionMetaKey(VERSION_KEY) + .setMappings(request.mappings().get("_doc")) + .setSettings(request.settings()) + .setPrimaryIndex(".fleet-artifacts-" + CURRENT_INDEX_VERSION) + .setIndexPattern(".fleet-artifacts*") + .setAliasName(".fleet-artifacts") + .setDescription("Fleet artifacts") + .build(); + } + + private String loadTemplateSource(String resource) { + return TemplateUtils.loadTemplate(resource, Version.CURRENT.toString(), MAPPING_VERSION_VARIABLE); + } } diff --git a/x-pack/plugin/fleet/src/test/java/org/elasticsearch/xpack/fleet/FleetTests.java b/x-pack/plugin/fleet/src/test/java/org/elasticsearch/xpack/fleet/FleetTests.java index 2ffb8e3f37963..3bbacb1860d34 100644 --- a/x-pack/plugin/fleet/src/test/java/org/elasticsearch/xpack/fleet/FleetTests.java +++ b/x-pack/plugin/fleet/src/test/java/org/elasticsearch/xpack/fleet/FleetTests.java @@ -25,7 +25,15 @@ public void testFleetIndexNames() { assertThat( fleetDescriptors.stream().map(SystemIndexDescriptor::getIndexPattern).collect(Collectors.toList()), - containsInAnyOrder(".fleet-servers*", ".fleet-policies*", ".fleet-agents*", ".fleet-actions*") + containsInAnyOrder( + ".fleet-servers*", + ".fleet-policies-[0-9]+*", + ".fleet-agents*", + ".fleet-actions*", + ".fleet-policies-leader*", + ".fleet-enrollment-api-keys*", + ".fleet-artifacts*" + ) ); assertTrue(fleetDescriptors.stream().anyMatch(d -> d.matchesIndexPattern(".fleet-servers"))); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationUtils.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationUtils.java index 03beb572ad126..8a176b6d7dd96 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationUtils.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationUtils.java @@ -26,6 +26,7 @@ import static org.elasticsearch.xpack.core.ClientHelper.ASYNC_SEARCH_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.DEPRECATION_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.ENRICH_ORIGIN; +import static org.elasticsearch.xpack.core.ClientHelper.FLEET_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.IDP_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.INDEX_LIFECYCLE_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.LOGSTASH_MANAGEMENT_ORIGIN; @@ -127,6 +128,7 @@ public static void switchUserBasedOnActionOriginAndExecute(ThreadContext threadC case STACK_ORIGIN: case SEARCHABLE_SNAPSHOTS_ORIGIN: case LOGSTASH_MANAGEMENT_ORIGIN: + case FLEET_ORIGIN: case TASKS_ORIGIN: // TODO use a more limited user for tasks securityContext.executeAsUser(XPackUser.INSTANCE, consumer, Version.CURRENT); break;