Skip to content

Commit fc13f5a

Browse files
committed
New privilege evaluation implementation
Signed-off-by: Nils Bandener <nils.bandener@eliatra.com>
1 parent 5af5d01 commit fc13f5a

File tree

68 files changed

+3694
-2044
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+3694
-2044
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package org.opensearch.security;
2+
3+
import java.util.ArrayList;
4+
import java.util.Iterator;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
9+
import com.fasterxml.jackson.databind.JsonNode;
10+
import org.junit.Test;
11+
import org.junit.runner.RunWith;
12+
13+
import org.opensearch.action.admin.indices.alias.IndicesAliasesRequest;
14+
import org.opensearch.action.admin.indices.create.CreateIndexRequest;
15+
import org.opensearch.action.admin.indices.create.CreateIndexResponse;
16+
import org.opensearch.action.admin.indices.refresh.RefreshRequest;
17+
import org.opensearch.common.xcontent.XContentType;
18+
import org.opensearch.core.common.Strings;
19+
import org.opensearch.test.framework.TestSecurityConfig;
20+
import org.opensearch.test.framework.cluster.ClusterManager;
21+
import org.opensearch.test.framework.cluster.LocalCluster;
22+
import org.opensearch.test.framework.cluster.TestRestClient;
23+
import org.opensearch.transport.client.Client;
24+
25+
// io.netty, org.apache.lucene, java.io, java.nio, org.apache.logging.
26+
// org.jcp
27+
//java.security.Provider$Service
28+
//apple.security.AppleProvider$ProviderService
29+
@RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class)
30+
@ThreadLeakScope(ThreadLeakScope.Scope.NONE)
31+
public class PerfTest {
32+
33+
public static void createTestData(LocalCluster cluster) throws Exception {
34+
try (Client client = cluster.getInternalNodeClient()) {
35+
{
36+
CreateIndexRequest request = new CreateIndexRequest("test").settings(
37+
Map.of("index.number_of_shards", 3, "index.number_of_replicas", 1)
38+
);
39+
CreateIndexResponse response = client.admin().indices().create(request).actionGet();
40+
System.out.println(Strings.toString(XContentType.JSON, response));
41+
}
42+
43+
IndicesAliasesRequest indicesAliasesRequest = new IndicesAliasesRequest();
44+
45+
for (int i = 0; i < 1000; i++) {
46+
String index = ".kibana_t_" + i + "_001";
47+
CreateIndexRequest request = new CreateIndexRequest(index).settings(
48+
Map.of("index.number_of_shards", 1, "index.number_of_replicas", 0)
49+
);
50+
CreateIndexResponse response = client.admin().indices().create(request).actionGet();
51+
System.out.println(Strings.toString(XContentType.JSON, response));
52+
indicesAliasesRequest.addAliasAction(IndicesAliasesRequest.AliasActions.add().alias(".kibana_t_" + i).indices(index));
53+
}
54+
55+
client.admin().indices().aliases(indicesAliasesRequest).actionGet();
56+
client.admin().indices().refresh(new RefreshRequest()).actionGet();
57+
client.admin().indices().refresh(new RefreshRequest()).actionGet();
58+
59+
}
60+
}
61+
62+
@Test
63+
public void test() throws Exception {
64+
65+
try (
66+
LocalCluster cluster = new LocalCluster.Builder().clusterManager(ClusterManager.DEFAULT)
67+
.authc(TestSecurityConfig.AuthcDomain.AUTHC_HTTPBASIC_INTERNAL)
68+
.users(TestSecurityConfig.User.USER_ADMIN)
69+
.nodeSettings(Map.of("cluster_manager.throttling.thresholds.auto-create.value", 3000, "cluster.max_shards_per_node", 10000))
70+
.build()
71+
) {
72+
73+
cluster.before();
74+
75+
createTestData(cluster);
76+
77+
System.out.println("*** READY ***");
78+
79+
Thread.sleep(60 * 1000);
80+
81+
try (TestRestClient client = cluster.getRestClient(cluster.getAdminCertificate())) {
82+
for (int i = 0; i < 10000; i++) {
83+
StringBuilder bulkBody = new StringBuilder();
84+
for (int k = 0; k < 10; k++) {
85+
bulkBody.append("""
86+
{ "index": { "_index": "test" } }
87+
{ "title": "foo", "year": 2020}
88+
""");
89+
}
90+
try {
91+
TestRestClient.HttpResponse response = client.postJson("_bulk", bulkBody.toString());
92+
// if (response.getStatusCode() >= 300) {
93+
System.out.println(response.getBody());
94+
// }
95+
} catch (Exception e) {
96+
e.printStackTrace();
97+
}
98+
}
99+
}
100+
101+
}
102+
103+
}
104+
105+
static String parseNodeStatsResponse(TestRestClient.HttpResponse response) {
106+
if (response.getBody().contains("receive_timeout_transport_exception")) {
107+
return "TIMEOUT\n";
108+
} else {
109+
JsonNode responseJsonNode = response.bodyAsJsonNode();
110+
JsonNode nodes = responseJsonNode.get("nodes");
111+
Iterator<String> fieldNames = nodes.fieldNames();
112+
StringBuilder result = new StringBuilder();
113+
while (fieldNames.hasNext()) {
114+
String nodeId = fieldNames.next();
115+
JsonNode node = nodes.get(nodeId);
116+
JsonNode threadPool = node.get("thread_pool");
117+
JsonNode managementThreadPool = threadPool.get("management");
118+
result.append(
119+
nodeId
120+
+ ": management thread pool: active: "
121+
+ managementThreadPool.get("active")
122+
+ "/5"
123+
+ "; queue: "
124+
+ managementThreadPool.get("queue")
125+
+ "\n"
126+
);
127+
}
128+
129+
return result.toString();
130+
}
131+
}
132+
133+
static TestSecurityConfig.Role[] createTestRoles() {
134+
List<TestSecurityConfig.Role> result = new ArrayList<>();
135+
136+
for (int i = 0; i < 2500; i++) {
137+
result.add(new TestSecurityConfig.Role("role" + i).indexPermissions("crud").on("*example*", ".*example*"));
138+
}
139+
140+
return result.toArray(new TestSecurityConfig.Role[0]);
141+
}
142+
143+
static class State {
144+
int pendingCreateUserRequests = 0;
145+
}
146+
}

src/integrationTest/java/org/opensearch/security/privileges/IndexRequestModifierTest.java

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,16 @@
1111

1212
package org.opensearch.security.privileges;
1313

14+
import java.util.Arrays;
15+
import java.util.Collection;
16+
import java.util.Collections;
17+
import java.util.Map;
18+
1419
import org.junit.Test;
1520
import org.junit.runner.RunWith;
1621
import org.junit.runners.Parameterized;
1722
import org.junit.runners.Suite;
23+
1824
import org.opensearch.action.ActionRequest;
1925
import org.opensearch.action.IndicesRequest;
2026
import org.opensearch.action.OriginalIndices;
@@ -29,23 +35,18 @@
2935
import org.opensearch.common.util.concurrent.ThreadContext;
3036
import org.opensearch.security.util.MockIndexMetadataBuilder;
3137

32-
import java.util.Arrays;
33-
import java.util.Collection;
34-
import java.util.Collections;
35-
import java.util.Map;
36-
3738
import static org.junit.Assert.assertArrayEquals;
3839
import static org.junit.Assert.assertEquals;
3940
import static org.junit.Assert.assertFalse;
4041
import static org.junit.Assert.assertTrue;
4142

4243
@RunWith(Suite.class)
43-
@Suite.SuiteClasses({
44-
IndexRequestModifierTest.SetLocalIndices.class,
45-
IndexRequestModifierTest.SetLocalIndicesToEmpty.class })
44+
@Suite.SuiteClasses({ IndexRequestModifierTest.SetLocalIndices.class, IndexRequestModifierTest.SetLocalIndicesToEmpty.class })
4645
public class IndexRequestModifierTest {
4746

48-
static final IndexNameExpressionResolver indexNameExpressionResolver = new IndexNameExpressionResolver(new ThreadContext(Settings.EMPTY));
47+
static final IndexNameExpressionResolver indexNameExpressionResolver = new IndexNameExpressionResolver(
48+
new ThreadContext(Settings.EMPTY)
49+
);
4950
static final Metadata metadata = MockIndexMetadataBuilder.indices("index", "index1", "index2", "index3").build();
5051
final static ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metadata(metadata).build();
5152
static final IndicesRequestModifier subject = new IndicesRequestModifier();
@@ -58,17 +59,20 @@ public void basic() {
5859

5960
boolean success = subject.setLocalIndices(request, resolvedIndices, Collections.singletonList("index1"));
6061
assertTrue(success);
61-
assertArrayEquals(new String [] {"index1"}, request.indices());
62+
assertArrayEquals(new String[] { "index1" }, request.indices());
6263
}
6364

6465
@Test
6566
public void withRemote() {
66-
ResolvedIndices resolvedIndices = ResolvedIndices.of("index1").withRemoteIndices(Map.of("remote", new OriginalIndices(new String[] {"index_remote"}, IndicesOptions.LENIENT_EXPAND_OPEN)));
67+
ResolvedIndices resolvedIndices = ResolvedIndices.of("index1")
68+
.withRemoteIndices(
69+
Map.of("remote", new OriginalIndices(new String[] { "index_remote" }, IndicesOptions.LENIENT_EXPAND_OPEN))
70+
);
6771
SearchRequest request = new SearchRequest("index1", "index2", "index3", "remote:index_remote");
6872

6973
boolean success = subject.setLocalIndices(request, resolvedIndices, Collections.singletonList("index1"));
7074
assertTrue(success);
71-
assertArrayEquals(new String [] {"index1", "remote:index_remote"}, request.indices());
75+
assertArrayEquals(new String[] { "index1", "remote:index_remote" }, request.indices());
7276
}
7377

7478
@Test
@@ -78,8 +82,8 @@ public void empty() {
7882

7983
boolean success = subject.setLocalIndices(request, resolvedIndices, Collections.emptyList());
8084
assertTrue(success);
81-
String [] finalResolvedIndices = indexNameExpressionResolver.concreteIndexNames(clusterState, request);
82-
assertArrayEquals(new String [0], finalResolvedIndices);
85+
String[] finalResolvedIndices = indexNameExpressionResolver.concreteIndexNames(clusterState, request);
86+
assertArrayEquals(new String[0], finalResolvedIndices);
8387
}
8488

8589
@Test
@@ -95,7 +99,6 @@ public void unsupportedType() {
9599
@RunWith(Parameterized.class)
96100
public static class SetLocalIndicesToEmpty {
97101

98-
99102
String description;
100103
IndicesRequest request;
101104

@@ -105,53 +108,49 @@ public void setLocalIndicesToEmpty() {
105108
ResolvedIndices resolvedIndices = ResolvedIndices.of("index");
106109

107110
if (Arrays.asList(request.indices()).contains("remote:index")) {
108-
resolvedIndices = resolvedIndices.withRemoteIndices(Map.of("remote", new OriginalIndices(new String [] {"index"}, request.indicesOptions())));
111+
resolvedIndices = resolvedIndices.withRemoteIndices(
112+
Map.of("remote", new OriginalIndices(new String[] { "index" }, request.indicesOptions()))
113+
);
109114
}
110115

111116
boolean success = subject.setLocalIndicesToEmpty((ActionRequest) request, resolvedIndices);
112117

113118
if (!(request instanceof IndicesRequest.Replaceable)) {
114119
assertFalse(success);
115-
} else
116-
if (!request.indicesOptions().allowNoIndices()) {
120+
} else if (!request.indicesOptions().allowNoIndices()) {
117121
assertFalse(success);
118122
} else {
119123
assertTrue(success);
120124

121-
String [] finalResolvedIndices = indexNameExpressionResolver.concreteIndexNames(clusterState, request);
125+
String[] finalResolvedIndices = indexNameExpressionResolver.concreteIndexNames(clusterState, request);
122126

123-
assertEquals("Resolved to empty indices: " + Arrays.asList(finalResolvedIndices), 0, finalResolvedIndices.length);
127+
assertEquals("Resolved to empty indices: " + Arrays.asList(finalResolvedIndices), 0, finalResolvedIndices.length);
124128
}
125129
}
126130

127-
128131
@Parameterized.Parameters(name = "{0}")
129132
public static Collection<Object[]> params() {
130133
return Arrays.asList(
131-
new Object [] {
132-
"lenient expand open", new SearchRequest("index").indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN)
133-
},
134-
new Object [] {
135-
"lenient expand open/closed", new SearchRequest("index").indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN_CLOSED)
136-
},
137-
new Object [] {
138-
"lenient expand open/closed/hidden", new SearchRequest("index").indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN_CLOSED_HIDDEN)
139-
},
140-
new Object [] {
141-
"allow no indices", new SearchRequest("index").indicesOptions(IndicesOptions.fromOptions(false, true, false, false))
142-
},
143-
new Object [] {
144-
"ignore unavailable", new SearchRequest("index").indicesOptions(IndicesOptions.fromOptions(true, false, false, false))
145-
},
146-
new Object [] {
147-
"strict single index", new SearchRequest("index").indicesOptions(IndicesOptions.STRICT_SINGLE_INDEX_NO_EXPAND_FORBID_CLOSED)
148-
},
149-
new Object [] {
150-
"with remote index", new SearchRequest("index", "remote:index").indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN)
151-
},
152-
new Object [] {
153-
"not implementing IndicesRequest.Replaceable", new IndexRequest("index")
154-
}
134+
new Object[] { "lenient expand open", new SearchRequest("index").indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN) },
135+
new Object[] {
136+
"lenient expand open/closed",
137+
new SearchRequest("index").indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN_CLOSED) },
138+
new Object[] {
139+
"lenient expand open/closed/hidden",
140+
new SearchRequest("index").indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN_CLOSED_HIDDEN) },
141+
new Object[] {
142+
"allow no indices",
143+
new SearchRequest("index").indicesOptions(IndicesOptions.fromOptions(false, true, false, false)) },
144+
new Object[] {
145+
"ignore unavailable",
146+
new SearchRequest("index").indicesOptions(IndicesOptions.fromOptions(true, false, false, false)) },
147+
new Object[] {
148+
"strict single index",
149+
new SearchRequest("index").indicesOptions(IndicesOptions.STRICT_SINGLE_INDEX_NO_EXPAND_FORBID_CLOSED) },
150+
new Object[] {
151+
"with remote index",
152+
new SearchRequest("index", "remote:index").indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN) },
153+
new Object[] { "not implementing IndicesRequest.Replaceable", new IndexRequest("index") }
155154
);
156155

157156
}

src/integrationTest/java/org/opensearch/security/privileges/IndicesRequestResolverTest.java

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,22 @@
1010
*/
1111

1212
package org.opensearch.security.privileges;
13-
import org.junit.Test;
14-
import org.opensearch.action.admin.cluster.state.ClusterStateRequest;
15-
import org.opensearch.action.admin.cluster.stats.ClusterStatsRequest;
16-
import org.opensearch.action.admin.indices.settings.put.UpdateSettingsRequest;
17-
import org.opensearch.action.search.SearchRequest;
18-
import org.opensearch.action.support.ActionRequestMetadata;
13+
1914
import org.opensearch.cluster.ClusterState;
2015
import org.opensearch.cluster.metadata.IndexNameExpressionResolver;
2116
import org.opensearch.cluster.metadata.Metadata;
22-
import org.opensearch.cluster.metadata.ResolvedIndices;
2317
import org.opensearch.common.settings.Settings;
2418
import org.opensearch.common.util.concurrent.ThreadContext;
2519
import org.opensearch.security.util.MockIndexMetadataBuilder;
26-
import org.opensearch.security.util.MockPrivilegeEvaluationContextBuilder;
27-
28-
import java.util.Optional;
29-
import java.util.Set;
30-
31-
import static org.mockito.Mockito.mock;
32-
import static org.mockito.Mockito.when;
33-
34-
import static org.junit.Assert.assertArrayEquals;
35-
import static org.junit.Assert.assertEquals;
36-
import static org.junit.Assert.assertFalse;
37-
import static org.junit.Assert.assertTrue;
3820

3921
public class IndicesRequestResolverTest {
4022

4123
static final Metadata metadata = MockIndexMetadataBuilder.indices("index1", "index2", "index3").build();
4224
final static ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metadata(metadata).build();
43-
static final IndicesRequestResolver subject = new IndicesRequestResolver(new IndexNameExpressionResolver(new ThreadContext(Settings.EMPTY)));
44-
25+
static final IndicesRequestResolver subject = new IndicesRequestResolver(
26+
new IndexNameExpressionResolver(new ThreadContext(Settings.EMPTY))
27+
);
28+
/*
4529
@Test
4630
public void resolve_normal() {
4731
SearchRequest request = new SearchRequest("index1");
@@ -82,5 +66,5 @@ public void resolve_withPrivilegesEvaluationContext() {
8266
8367
ResolvedIndices returnedResolvedIndices = subject.resolve(request, actionRequestMetadata, context);
8468
assertEquals(Set.of("index1", "index2", "index3"), returnedResolvedIndices.local().names());
85-
}
69+
}*/
8670
}

src/integrationTest/java/org/opensearch/security/privileges/RestEndpointPermissionTests.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.opensearch.security.dlic.rest.api.Endpoint;
4848
import org.opensearch.security.dlic.rest.api.RestApiAdminPrivilegesEvaluator.PermissionBuilder;
4949
import org.opensearch.security.privileges.actionlevel.RoleBasedActionPrivileges;
50+
import org.opensearch.security.privileges.actionlevel.RuntimeOptimizedActionPrivileges;
5051
import org.opensearch.security.securityconf.FlattenedActionGroups;
5152
import org.opensearch.security.securityconf.impl.CType;
5253
import org.opensearch.security.securityconf.impl.SecurityDynamicConfiguration;
@@ -117,7 +118,12 @@ static String[] allRestApiPermissions() {
117118
final RoleBasedActionPrivileges actionPrivileges;
118119

119120
public RestEndpointPermissionTests() throws IOException {
120-
this.actionPrivileges = new RoleBasedActionPrivileges(createRolesConfig(), FlattenedActionGroups.EMPTY, Settings.EMPTY);
121+
this.actionPrivileges = new RoleBasedActionPrivileges(
122+
createRolesConfig(),
123+
FlattenedActionGroups.EMPTY,
124+
RuntimeOptimizedActionPrivileges.SpecialIndexProtection.NONE,
125+
Settings.EMPTY
126+
);
121127
}
122128

123129
@Test

0 commit comments

Comments
 (0)