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;