Skip to content

Commit

Permalink
Tests
Browse files Browse the repository at this point in the history
Signed-off-by: Nils Bandener <[email protected]>
  • Loading branch information
nibix committed Oct 3, 2024
1 parent 3ed06c7 commit d035766
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import org.opensearch.action.support.IndicesOptions;
import org.opensearch.cluster.metadata.IndexAbstraction;
import org.opensearch.cluster.metadata.IndexMetadata;
import org.opensearch.cluster.metadata.IndexNameExpressionResolver;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.util.concurrent.ThreadContext;
Expand All @@ -39,6 +40,7 @@
import org.opensearch.security.securityconf.impl.CType;
import org.opensearch.security.securityconf.impl.SecurityDynamicConfiguration;
import org.opensearch.security.securityconf.impl.v7.RoleV7;
import org.opensearch.security.support.WildcardMatcher;
import org.opensearch.security.user.User;
import org.opensearch.security.util.MockIndexMetadataBuilder;

Expand All @@ -61,6 +63,7 @@
ActionPrivilegesTest.ClusterPrivileges.class,
ActionPrivilegesTest.IndexPrivileges.IndicesAndAliases.class,
ActionPrivilegesTest.IndexPrivileges.DataStreams.class,
ActionPrivilegesTest.Misc.class,
ActionPrivilegesTest.StatefulIndexPrivilegesHeapSize.class })
public class ActionPrivilegesTest {
public static class ClusterPrivileges {
Expand Down Expand Up @@ -102,6 +105,21 @@ public void notWellKnown() throws Exception {
);
}

@Test
public void wildcard() throws Exception {
SecurityDynamicConfiguration<RoleV7> roles = SecurityDynamicConfiguration.fromYaml("test_role:\n" + //
" cluster_permissions:\n" + //
" - '*'", CType.ROLES);

ActionPrivileges subject = new ActionPrivileges(roles, FlattenedActionGroups.EMPTY, null, Settings.EMPTY);

assertThat(subject.hasClusterPrivilege(ctx("test_role"), "cluster:whatever"), isAllowed());
assertThat(
subject.hasClusterPrivilege(ctx("other_role"), "cluster:whatever"),
isForbidden(missingPrivileges("cluster:whatever"))
);
}

@Test
public void explicit_wellKnown() throws Exception {
SecurityDynamicConfiguration<RoleV7> roles = SecurityDynamicConfiguration.fromYaml("non_explicit_role:\n" + //
Expand Down Expand Up @@ -213,6 +231,26 @@ public void hasAny_notWellKnown() throws Exception {
subject.hasAnyClusterPrivilege(ctx("test_role"), ImmutableSet.of("cluster:monitor/other")),
isForbidden(missingPrivileges("cluster:monitor/other"))
);
assertThat(
subject.hasAnyClusterPrivilege(ctx("test_role"), ImmutableSet.of("cluster:monitor/other", "cluster:monitor/yetanother")),
isForbidden()
);
}

@Test
public void hasAny_wildcard() throws Exception {
SecurityDynamicConfiguration<RoleV7> roles = SecurityDynamicConfiguration.fromYaml("test_role:\n" + //
" cluster_permissions:\n" + //
" - '*'", CType.ROLES);

ActionPrivileges subject = new ActionPrivileges(roles, FlattenedActionGroups.EMPTY, null, Settings.EMPTY);

assertThat(subject.hasAnyClusterPrivilege(ctx("test_role"), ImmutableSet.of("cluster:whatever")), isAllowed());

assertThat(
subject.hasAnyClusterPrivilege(ctx("other_role"), ImmutableSet.of("cluster:whatever")),
isForbidden(missingPrivileges("cluster:whatever"))
);
}
}

Expand Down Expand Up @@ -282,6 +320,19 @@ public void positive_partial2() throws Exception {
}
}

@Test
public void positive_noLocal() throws Exception {
IndexResolverReplacer.Resolved resolved = new IndexResolverReplacer.Resolved(
ImmutableSet.of(),
ImmutableSet.of(),
ImmutableSet.of("remote:a"),
ImmutableSet.of("remote:a"),
IndicesOptions.LENIENT_EXPAND_OPEN
);
PrivilegesEvaluatorResponse result = subject.hasIndexPrivilege(ctx("test_role"), requiredActions, resolved);
assertThat(result, isAllowed());
}

@Test
public void negative_wrongRole() throws Exception {
PrivilegesEvaluationContext ctx = ctx("other_role");
Expand Down Expand Up @@ -592,7 +643,6 @@ static IndexResolverReplacer.Resolved resolved(String... indices) {
IndicesOptions.LENIENT_EXPAND_OPEN
);
}

}

static class IndexSpec {
Expand Down Expand Up @@ -717,6 +767,75 @@ enum Statefulness {
}
}

public static class Misc {
@Test
public void relevantOnly_identity() throws Exception {
Map<String, IndexAbstraction> metadata = //
indices("index_a11", "index_a12", "index_b")//
.alias("alias_a")
.of("index_a11", "index_a12")//
.build()
.getIndicesLookup();

Assert.assertTrue(
"relevantOnly() returned identical object",
ActionPrivileges.StatefulIndexPrivileges.relevantOnly(metadata, null) == metadata
);
}

@Test
public void relevantOnly_closed() throws Exception {
Map<String, IndexAbstraction> metadata = indices("index_open_1", "index_open_2")//
.index("index_closed", IndexMetadata.State.CLOSE)
.build()
.getIndicesLookup();

Assert.assertNotNull("Original metadata contains index_open_1", metadata.get("index_open_1"));
Assert.assertNotNull("Original metadata contains index_closed", metadata.get("index_closed"));

Map<String, IndexAbstraction> filteredMetadata = ActionPrivileges.StatefulIndexPrivileges.relevantOnly(metadata, null);

Assert.assertNotNull("Filtered metadata contains index_open_1", filteredMetadata.get("index_open_1"));
Assert.assertNull("Filtered metadata does not contain index_closed", filteredMetadata.get("index_closed"));
}

@Test
public void relevantOnly_dataStreamBackingIndices() throws Exception {
Map<String, IndexAbstraction> metadata = dataStreams("data_stream_1").build().getIndicesLookup();

Assert.assertNotNull("Original metadata contains backing index", metadata.get(".ds-data_stream_1-000001"));
Assert.assertNotNull("Original metadata contains data stream", metadata.get("data_stream_1"));

Map<String, IndexAbstraction> filteredMetadata = ActionPrivileges.StatefulIndexPrivileges.relevantOnly(metadata, null);

Assert.assertNull("Filtered metadata does not contain backing index", filteredMetadata.get(".ds-data_stream_1-000001"));
Assert.assertNotNull("Filtered metadata contains data stream", filteredMetadata.get("data_stream_1"));
}

@Test
public void relevantOnly_includePattern() throws Exception {
Map<String, IndexAbstraction> metadata = //
indices("index_a11", "index_a12", "index_b1")//
.alias("alias_a")
.of("index_a11")//
.build()
.getIndicesLookup();

Assert.assertNotNull("Original metadata contains index_a11", metadata.get("index_a11"));
Assert.assertNotNull("Original metadata contains index_b1", metadata.get("index_b1"));
Assert.assertNotNull("Original metadata contains alias_a", metadata.get("alias_a"));

Map<String, IndexAbstraction> filteredMetadata = ActionPrivileges.StatefulIndexPrivileges.relevantOnly(
metadata,
WildcardMatcher.from("index_a*", "alias_a*")
);

Assert.assertNotNull("Filtered metadata contains index_a11", filteredMetadata.get("index_a11"));
Assert.assertNull("Filtered metadata does not contain index_b1", filteredMetadata.get("index_b1"));
Assert.assertNotNull("Filtered metadata contains alias_a", filteredMetadata.get("alias_a"));
}
}

/**
* Verifies that the heap size used by StatefulIndexPrivileges stays within expected bounds.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.time.ZonedDateTime;
import java.time.temporal.ChronoField;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.junit.Test;

Expand All @@ -22,10 +23,13 @@
import org.opensearch.common.settings.Settings;
import org.opensearch.common.util.concurrent.ThreadContext;
import org.opensearch.security.resolver.IndexResolverReplacer;
import org.opensearch.security.support.WildcardMatcher;
import org.opensearch.security.user.User;

import static org.opensearch.security.util.MockIndexMetadataBuilder.indices;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class IndexPatternTest {
final static int CURRENT_YEAR = ZonedDateTime.now().get(ChronoField.YEAR);
Expand All @@ -45,85 +49,142 @@ public class IndexPatternTest {
.of("index_current_year")//
.alias("alias_year_" + NEXT_YEAR)
.of("index_next_year")//

.build();
final static ClusterState CLUSTER_STATE = ClusterState.builder(ClusterState.EMPTY_STATE).metadata(INDEX_METADATA).build();

@Test
public void constantIndex() throws Exception {
IndexPattern indexPattern = IndexPattern.from("index_a11");
assertTrue(indexPattern.hasStaticPattern());
assertFalse(indexPattern.hasDynamicPattern());
assertTrue(indexPattern.dynamicOnly().isEmpty());
assertEquals("index_a11", indexPattern.toString());

assertTrue(indexPattern.matches("index_a11", ctx(), INDEX_METADATA.getIndicesLookup()));
assertFalse(indexPattern.matches("index_a12", ctx(), INDEX_METADATA.getIndicesLookup()));
}

@Test
public void constantAlias() throws Exception {
IndexPattern indexPattern = IndexPattern.from("alias_a");
assertTrue(indexPattern.hasStaticPattern());
assertFalse(indexPattern.hasDynamicPattern());

assertTrue(indexPattern.matches("alias_a", ctx(), INDEX_METADATA.getIndicesLookup()));
assertFalse(indexPattern.matches("alias_a1", ctx(), INDEX_METADATA.getIndicesLookup()));
}

@Test
public void constantAlias_onIndex() throws Exception {
IndexPattern indexPattern = IndexPattern.from("alias_a");
assertTrue(indexPattern.hasStaticPattern());
assertFalse(indexPattern.hasDynamicPattern());

assertTrue(indexPattern.matches("index_a11", ctx(), INDEX_METADATA.getIndicesLookup()));
assertFalse(indexPattern.matches("index_b1", ctx(), INDEX_METADATA.getIndicesLookup()));
}

@Test
public void constantDataStream_onIndex() throws Exception {
IndexPattern indexPattern = IndexPattern.from("data_stream_a1");
assertTrue(indexPattern.hasStaticPattern());
assertFalse(indexPattern.hasDynamicPattern());

assertTrue(indexPattern.matches(".ds-data_stream_a1-000001", ctx(), INDEX_METADATA.getIndicesLookup()));
assertFalse(indexPattern.matches(".ds-data_stream_a2-000001", ctx(), INDEX_METADATA.getIndicesLookup()));
}

@Test
public void patternIndex() throws Exception {
IndexPattern indexPattern = IndexPattern.from("index_a1*");
assertTrue(indexPattern.hasStaticPattern());
assertFalse(indexPattern.hasDynamicPattern());

assertTrue(indexPattern.matches("index_a11", ctx(), INDEX_METADATA.getIndicesLookup()));
assertFalse(indexPattern.matches("index_a21", ctx(), INDEX_METADATA.getIndicesLookup()));
}

@Test
public void patternAlias() throws Exception {
IndexPattern indexPattern = IndexPattern.from("alias_a*");
assertTrue(indexPattern.hasStaticPattern());
assertFalse(indexPattern.hasDynamicPattern());

assertTrue(indexPattern.matches("alias_a", ctx(), INDEX_METADATA.getIndicesLookup()));
assertFalse(indexPattern.matches("alias_b", ctx(), INDEX_METADATA.getIndicesLookup()));
}

@Test
public void patternAlias_onIndex() throws Exception {
IndexPattern indexPattern = IndexPattern.from("alias_a*");
assertTrue(indexPattern.hasStaticPattern());
assertFalse(indexPattern.hasDynamicPattern());

assertTrue(indexPattern.matches("index_a11", ctx(), INDEX_METADATA.getIndicesLookup()));
assertFalse(indexPattern.matches("index_b1", ctx(), INDEX_METADATA.getIndicesLookup()));
}

@Test
public void patternDataStream_onIndex() throws Exception {
IndexPattern indexPattern = IndexPattern.from("data_stream_a*");
assertTrue(indexPattern.hasStaticPattern());
assertFalse(indexPattern.hasDynamicPattern());

assertTrue(indexPattern.matches(".ds-data_stream_a1-000001", ctx(), INDEX_METADATA.getIndicesLookup()));
assertFalse(indexPattern.matches(".ds-data_stream_b1-000001", ctx(), INDEX_METADATA.getIndicesLookup()));
}

@Test
public void dateMathIndex() throws Exception {
IndexPattern indexPattern = IndexPattern.from("<index_year_{now/y{yyyy}}>");
assertFalse(indexPattern.hasStaticPattern());
assertTrue(indexPattern.hasDynamicPattern());
assertEquals("index_a11", indexPattern.toString());

assertTrue(indexPattern.matches("index_year_" + CURRENT_YEAR, ctx(), INDEX_METADATA.getIndicesLookup()));
assertFalse(indexPattern.matches("index_year_" + NEXT_YEAR, ctx(), INDEX_METADATA.getIndicesLookup()));
}

@Test
public void dateMathAlias_onIndex() throws Exception {
IndexPattern indexPattern = IndexPattern.from("<alias_year_{now/y{yyyy}}>");
assertFalse(indexPattern.hasStaticPattern());
assertTrue(indexPattern.hasDynamicPattern());

assertTrue(indexPattern.matches("index_current_year", ctx(), INDEX_METADATA.getIndicesLookup()));
assertFalse(indexPattern.matches("index_next_year", ctx(), INDEX_METADATA.getIndicesLookup()));
}

@Test
public void templatedIndex() throws Exception {
IndexPattern indexPattern = IndexPattern.from("index_${attrs.a11}");
assertFalse(indexPattern.hasStaticPattern());
assertTrue(indexPattern.hasDynamicPattern());
assertEquals(indexPattern, indexPattern.dynamicOnly());

assertTrue(indexPattern.matches("index_a11", ctx(), INDEX_METADATA.getIndicesLookup()));
assertFalse(indexPattern.matches("index_a12", ctx(), INDEX_METADATA.getIndicesLookup()));
}

@Test
public void mixed() throws Exception {
IndexPattern indexPattern = IndexPattern.from("index_${attrs.a11}", "index_a12");
assertTrue(indexPattern.hasStaticPattern());
assertTrue(indexPattern.hasDynamicPattern());

assertEquals(WildcardMatcher.from("index_a12"), indexPattern.getStaticPattern());
assertEquals(IndexPattern.from("index_${attrs.a11}"), indexPattern.dynamicOnly());
}

private static PrivilegesEvaluationContext ctx() {
IndexNameExpressionResolver indexNameExpressionResolver = new IndexNameExpressionResolver(new ThreadContext(Settings.EMPTY));
IndexResolverReplacer indexResolverReplacer = new IndexResolverReplacer(indexNameExpressionResolver, () -> CLUSTER_STATE, null);
User user = new User("test_user");
user.addAttributes(ImmutableMap.of("attrs.a11", "a11"));
user.addAttributes(ImmutableMap.of("attrs.year", "year"));

return new PrivilegesEvaluationContext(
new User("test_user"),
user,
ImmutableSet.of(),
"indices:action/test",
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ public Metadata build() {
}

public MockIndexMetadataBuilder index(String indexName) {
getIndexMetadataBuilder(indexName);
return index(indexName, IndexMetadata.State.OPEN);
}

public MockIndexMetadataBuilder index(String indexName, IndexMetadata.State state) {
getIndexMetadataBuilder(indexName, state);
return this;
}

Expand All @@ -85,7 +89,7 @@ public MockIndexMetadataBuilder dataStream(String dataStream, int generations) {
for (int i = 1; i <= generations; i++) {
String backingIndexName = DataStream.getDefaultBackingIndexName(dataStream, i);
backingIndices.add(new Index(backingIndexName, backingIndexName));
getIndexMetadataBuilder(backingIndexName);
getIndexMetadataBuilder(backingIndexName, IndexMetadata.State.OPEN);
}

DataStream dataStreamMetadata = new DataStream(dataStream, new DataStream.TimestampField("@timestamp"), backingIndices);
Expand All @@ -94,16 +98,15 @@ public MockIndexMetadataBuilder dataStream(String dataStream, int generations) {
return this;
}

private IndexMetadata.Builder getIndexMetadataBuilder(String indexName) {
private IndexMetadata.Builder getIndexMetadataBuilder(String indexName, IndexMetadata.State state) {
IndexMetadata.Builder result = this.nameToIndexMetadataBuilderMap.get(indexName);

if (result != null) {
return result;
}

result = new IndexMetadata.Builder(indexName).settings(
Settings.builder().put(INDEX_SETTINGS).put(IndexMetadata.SETTING_INDEX_UUID, indexName).build()
);
result = new IndexMetadata.Builder(indexName).state(state)
.settings(Settings.builder().put(INDEX_SETTINGS).put(IndexMetadata.SETTING_INDEX_UUID, indexName).build());

this.nameToIndexMetadataBuilderMap.put(indexName, result);

Expand All @@ -121,7 +124,7 @@ public MockIndexMetadataBuilder of(String... indices) {
AliasMetadata aliasMetadata = new AliasMetadata.Builder(aliasName).build();

for (String index : indices) {
IndexMetadata.Builder indexMetadataBuilder = getIndexMetadataBuilder(index);
IndexMetadata.Builder indexMetadataBuilder = getIndexMetadataBuilder(index, IndexMetadata.State.OPEN);
indexMetadataBuilder.putAlias(aliasMetadata);
}

Expand Down
Loading

0 comments on commit d035766

Please sign in to comment.