From 1a57120a6b419bda7db3490aaf368172b5632237 Mon Sep 17 00:00:00 2001 From: Alexander Reelsen Date: Mon, 10 Jul 2017 16:15:13 +0200 Subject: [PATCH] Security: Add index template permissions for system user (elastic/x-pack-elasticsearch#1937) As the TemplateUpgradeService requires permissions to add and delete index template, we have to grant those to the _system user. This commit adds such permissions plus an integration test. Original commit: elastic/x-pack-elasticsearch@a76ca9c7384f08f90a3b10cfa8a11e80c1ccba23 --- .../authz/privilege/SystemPrivilege.java | 4 +- .../xpack/security/TemplateUpgraderTests.java | 74 +++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 plugin/src/test/java/org/elasticsearch/xpack/security/TemplateUpgraderTests.java diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authz/privilege/SystemPrivilege.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authz/privilege/SystemPrivilege.java index c2fc2375c90..2a75f33cb1b 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authz/privilege/SystemPrivilege.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authz/privilege/SystemPrivilege.java @@ -20,7 +20,9 @@ public final class SystemPrivilege extends Privilege { "indices:monitor/*", // added for monitoring "cluster:monitor/*", // added for monitoring "cluster:admin/reroute", // added for DiskThresholdDecider.DiskListener - "indices:admin/mapping/put" // needed for recovery and shrink api + "indices:admin/mapping/put", // needed for recovery and shrink api + "indices:admin/template/put", // needed for the TemplateUpgradeService + "indices:admin/template/delete" // needed for the TemplateUpgradeService ), Automatons.patterns("internal:transport/proxy/*"))); // no proxy actions for system user! private SystemPrivilege() { diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/TemplateUpgraderTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/TemplateUpgraderTests.java new file mode 100644 index 00000000000..7c254723868 --- /dev/null +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/TemplateUpgraderTests.java @@ -0,0 +1,74 @@ +/* + * 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.security; + +import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse; +import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.cluster.ClusterChangedEvent; +import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; +import org.elasticsearch.cluster.metadata.TemplateUpgradeService; +import org.elasticsearch.cluster.service.ClusterService; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.test.ESIntegTestCase.ClusterScope; +import org.elasticsearch.test.ESIntegTestCase.Scope; +import org.elasticsearch.test.SecurityIntegTestCase; +import org.elasticsearch.threadpool.ThreadPool; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; + +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.not; + +/** + * This test ensures, that the plugin template upgrader can add and remove + * templates when started within security, as this requires certain + * system priviliges + */ +@ClusterScope(maxNumDataNodes = 1, scope = Scope.SUITE, numClientNodes = 0) +public class TemplateUpgraderTests extends SecurityIntegTestCase { + + public void testTemplatesWorkAsExpected() throws Exception { + ClusterService clusterService = internalCluster().getInstance(ClusterService.class, internalCluster().getMasterName()); + ThreadPool threadPool = internalCluster().getInstance(ThreadPool.class, internalCluster().getMasterName()); + Client client = internalCluster().getInstance(Client.class, internalCluster().getMasterName()); + UnaryOperator> indexTemplateMetaDataUpgraders = map -> { + map.remove("removed-template"); + map.put("added-template", IndexTemplateMetaData.builder("added-template") + .order(1) + .patterns(Collections.singletonList(randomAlphaOfLength(10))).build()); + return map; + }; + + PutIndexTemplateResponse putIndexTemplateResponse = client().admin().indices().preparePutTemplate("removed-template") + .setOrder(1) + .setPatterns(Collections.singletonList(randomAlphaOfLength(10))) + .get(); + assertAcked(putIndexTemplateResponse); + assertTemplates("removed-template", "added-template"); + + TemplateUpgradeService templateUpgradeService = new TemplateUpgradeService(Settings.EMPTY, client, clusterService, threadPool, + Collections.singleton(indexTemplateMetaDataUpgraders)); + + // ensure the cluster listener gets triggered + ClusterChangedEvent event = new ClusterChangedEvent("testing", clusterService.state(), clusterService.state()); + templateUpgradeService.clusterChanged(event); + + assertBusy(() -> assertTemplates("added-template", "removed-template")); + } + + private void assertTemplates(String existingTemplate, String deletedTemplate) { + GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates().get(); + List templateNames = response.getIndexTemplates().stream().map(IndexTemplateMetaData::name).collect(Collectors.toList()); + assertThat(templateNames, hasItem(existingTemplate)); + assertThat(templateNames, not(hasItem(deletedTemplate))); + } +}