Snapshot Status: Allow system privilege to execute

As Elasticsearch 1.4.2 and below do not copy the headers in
TransportSnapshotsStatusAction, we need to allow the system user
to execute this in action, in order to see snapshots being currently
in progress.

This should be removed once we support elasticsearch 1.4.3

Closes elastic/elasticsearch#640

Original commit: elastic/x-pack-elasticsearch@00adf3dacf
This commit is contained in:
Alexander Reelsen 2015-01-26 13:29:25 +01:00
parent edc0bb86dc
commit 383e41d6ca
5 changed files with 114 additions and 1 deletions

View File

@ -85,7 +85,9 @@ public abstract class Privilege<P extends Privilege<P>> {
protected static final Predicate<String> PREDICATE = new AutomatonPredicate(patterns(
"internal:*",
"indices:monitor/*", // added for marvel
"cluster:monitor/*" // added for marvel
"cluster:monitor/*", // added for marvel
// TODO: remove again after 1.4.3
"cluster:admin/snapshot/status[nodes]"
));
private System() {

View File

@ -5,11 +5,14 @@
*/
package org.elasticsearch.integration;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.node.internal.InternalNode;
import org.junit.Test;
import java.io.File;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST;
@ -102,4 +105,47 @@ public class ClusterPrivilegeTests extends AbstractPrivilegeTests {
assertAccessIsDenied("user_c", "PUT", "/_cluster/settings", "{ \"transient\" : { \"indices.ttl.interval\": \"1m\" } }");
assertAccessIsDenied("user_c", "POST", "/_cluster/nodes/_all/_shutdown");
}
@Test
public void testThatSnapshotAndRestore() throws Exception {
File repositoryLocation = newTempDir();
String repoJson = "{ \"type\" : \"fs\", \"settings\" : { \"location\" : \"" + repositoryLocation.getAbsolutePath() + "\" } }";
assertAccessIsDenied("user_b", "PUT", "/_snapshot/my-repo", repoJson);
assertAccessIsDenied("user_c", "PUT", "/_snapshot/my-repo", repoJson);
assertAccessIsAllowed("user_a", "PUT", "/_snapshot/my-repo", repoJson);
ImmutableMap params = ImmutableMap.of("refresh", "true");
assertAccessIsDenied("user_a", "PUT", "/someindex/bar/1", "{ \"name\" : \"elasticsearch\" }", params);
assertAccessIsDenied("user_b", "PUT", "/someindex/bar/1", "{ \"name\" : \"elasticsearch\" }", params);
assertAccessIsAllowed("user_c", "PUT", "/someindex/bar/1", "{ \"name\" : \"elasticsearch\" }", params);
assertAccessIsAllowed("user_a", "PUT", "/_snapshot/my-repo/my-snapshot");
assertAccessIsDenied("user_b", "PUT", "/_snapshot/my-repo/my-snapshot");
assertAccessIsDenied("user_c", "PUT", "/_snapshot/my-repo/my-snapshot");
assertAccessIsDenied("user_b", "GET", "/_snapshot/my-repo/my-snapshot/_status");
assertAccessIsDenied("user_c", "GET", "/_snapshot/my-repo/my-snapshot/_status");
assertAccessIsAllowed("user_a", "GET", "/_snapshot/my-repo/my-snapshot/_status");
assertAccessIsDenied("user_a", "DELETE", "/someindex");
assertAccessIsDenied("user_b", "DELETE", "/someindex");
assertAccessIsAllowed("user_c", "DELETE", "/someindex");
ImmutableMap restoreParams = ImmutableMap.of("wait_for_completion", "true");
assertAccessIsDenied("user_b", "POST", "/_snapshot/my-repo/my-snapshot/_restore", null, restoreParams);
assertAccessIsDenied("user_c", "POST", "/_snapshot/my-repo/my-snapshot/_restore", null, restoreParams);
assertAccessIsAllowed("user_a", "POST", "/_snapshot/my-repo/my-snapshot/_restore", null, restoreParams);
assertAccessIsDenied("user_a", "GET", "/someindex/bar/1");
assertAccessIsDenied("user_b", "GET", "/someindex/bar/1");
assertAccessIsAllowed("user_c", "GET", "/someindex/bar/1");
assertAccessIsDenied("user_b", "DELETE", "/_snapshot/my-repo/my-snapshot");
assertAccessIsDenied("user_c", "DELETE", "/_snapshot/my-repo/my-snapshot");
assertAccessIsAllowed("user_a", "DELETE", "/_snapshot/my-repo/my-snapshot");
assertAccessIsDenied("user_b", "DELETE", "/_snapshot/my-repo");
assertAccessIsDenied("user_c", "DELETE", "/_snapshot/my-repo");
assertAccessIsAllowed("user_a", "DELETE", "/_snapshot/my-repo");
}
}

View File

@ -53,5 +53,13 @@ public class VersionCompatibilityTests extends ElasticsearchTestCase {
*
*/
assertThat("Remove workaround in LicenseService class when es core supports merging cluster level custom metadata", Version.CURRENT.onOrBefore(Version.V_1_4_2), is(true));
/**
* see https://github.com/elasticsearch/elasticsearch/pull/9409/
* This should be fixed in es 1.4.3 and up, thus can be removed
* You can also remove the SnapshotTests class then, as this functionality is also covered in the ClusterPrivilegeTests
* And remove the code in Privilege.System
*/
assertThat("Remove workaround to allow TransportNodesSnapshotsStatus be executed by the system user", Version.CURRENT.onOrBefore(Version.V_1_4_2), is(true));
}
}

View File

@ -176,9 +176,11 @@ public class PrivilegeTests extends ElasticsearchTestCase {
Predicate<String> predicate = Privilege.SYSTEM.predicate();
assertThat(predicate.apply("indices:monitor/whatever"), is(true));
assertThat(predicate.apply("cluster:monitor/whatever"), is(true));
assertThat(predicate.apply("cluster:admin/snapshot/status[nodes]"), is(true));
assertThat(predicate.apply("internal:whatever"), is(true));
assertThat(predicate.apply("indices:whatever"), is(false));
assertThat(predicate.apply("cluster:whatever"), is(false));
assertThat(predicate.apply("cluster:admin/snapshot/status"), is(false));
assertThat(predicate.apply("whatever"), is(false));
}

View File

@ -0,0 +1,55 @@
/*
* 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.shield.authz;
import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.collect.ImmutableMap;
import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotStatus;
import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusResponse;
import org.elasticsearch.cluster.metadata.SnapshotMetaData;
import org.elasticsearch.test.ShieldIntegrationTest;
import org.junit.Test;
import java.io.File;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
/**
* test to check if snapshotting and displaying of current snapshots work
* can be removed after 1.4.3 is released as this is included
*
*/
public class SnapshotTests extends ShieldIntegrationTest {
// TODO remove after upgrading to 1.4.3
@Test
public void testThatSnapshottingWorks() throws Exception {
File repositoryLocation = newTempDir();
assertAcked(client().admin().cluster().preparePutRepository("my-repo").setType("fs").setSettings(ImmutableMap.of("location", repositoryLocation.getAbsolutePath())));
client().prepareIndex("foo", "bar", "1").setSource("foo", "bar").get();
client().prepareIndex("foo", "bar", "2").setSource("foo", "bar").get();
client().prepareIndex("foo", "bar", "3").setSource("foo", "bar").get();
client().prepareIndex("foo", "bar", "4").setSource("foo", "bar").get();
client().prepareIndex("foo", "bar", "5").setSource("foo", "bar").get();
refresh();
// must be started async otherwise the code relevent path in TransportSnapshotsStatusAction about currently running snapshots is not executed
client().admin().cluster().prepareCreateSnapshot("my-repo", "my-snapshot").setIndices("foo").get();
SnapshotsStatusResponse snapshotsStatusResponse = client().admin().cluster().prepareSnapshotStatus("my-repo").setSnapshots("my-snapshot").get();
assertThat(snapshotsStatusResponse.getSnapshots(), hasSize(1));
SnapshotStatus snapshotStatus = snapshotsStatusResponse.getSnapshots().get(0);
assertThat(snapshotStatus.getState(), anyOf(is(SnapshotMetaData.State.STARTED), is(SnapshotMetaData.State.SUCCESS)));
assertAcked(client().admin().cluster().prepareDeleteSnapshot("my-repo", "my-snapshot").get());
assertAcked(client().admin().cluster().prepareDeleteRepository("my-repo"));
}
}