Skip to content

Commit a53a8a6

Browse files
DarshitChanpuracwperksMaciejMierzwa
authored
Authorize rest requests (#2753)
* WIP on rest layer authz Signed-off-by: Craig Perkins <cwperx@amazon.com> * WIP on rest-layer authz Signed-off-by: Craig Perkins <cwperx@amazon.com> * Extension handshake Signed-off-by: Craig Perkins <cwperx@amazon.com> * Extension TLS Signed-off-by: Craig Perkins <cwperx@amazon.com> * Remove SecurityRestFilterChanges to isolate extension TLS change Signed-off-by: Craig Perkins <cwperx@amazon.com> * Remove SecurityRestFilterChanges to isolate extension TLS change Signed-off-by: Craig Perkins <cwperx@amazon.com> * Remove SecurityRestFilterChanges to isolate extension TLS change Signed-off-by: Craig Perkins <cwperx@amazon.com> * Remove SecurityRestFilterChanges to isolate extension TLS change Signed-off-by: Craig Perkins <cwperx@amazon.com> * Remove SecurityRestFilterChanges to isolate extension TLS change Signed-off-by: Craig Perkins <cwperx@amazon.com> * WIP for HelloWorld sample extension role Signed-off-by: Craig Perkins <cwperx@amazon.com> * Initial implementation of authz check in REST layer Signed-off-by: Craig Perkins <cwperx@amazon.com> * Remove header Signed-off-by: Craig Perkins <cwperx@amazon.com> * Create authorizeRequest method Signed-off-by: Craig Perkins <cwperx@amazon.com> * small fix Signed-off-by: Craig Perkins <cwperx@amazon.com> * Change to ProtectedRoute Signed-off-by: Craig Perkins <cwperx@amazon.com> * Remove extension permissions Signed-off-by: Craig Perkins <cwperx@amazon.com> * Initial implementation of authz check in REST layer Signed-off-by: Craig Perkins <cwperx@amazon.com> * Extension TLS Signed-off-by: Craig Perkins <cwperx@amazon.com> * Adds dummy roles for testing rest authorization against legacy permissions Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Adds support for legacy permissions to perform rest authorization Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes white-space changes Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Rebases ConfigConstants with main Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Implements a new logic for rest permissions check to be more flexible Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes spotless errors Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Adds regex to match against current role permissions when comparing new permission with legacy ones Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Moves legacy permission check logic to ConfigModelV7 Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes extra new-lines Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes unused imports Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes out-of-scope white space changes Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes code-ql errors Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes spotless and code-ql errors Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes variable name and remove references to whitelist in javadoc Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Adds tests for rest layer privilege evaluator Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Adds license header to the test file Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Updates zstd dependency to fetch from core version.properties Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Updates action name in the regex to be dynamic Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Adds support for allowing evaluation against multiple actions names for a registered named route Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Updates tests Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Adds null check Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Makes authorize logic clearer to follow Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Adds extra check to ensure new actions are also evaluated against transport actions Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes spotless errors Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes security rest filter setup Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Removes extension reference Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * turn on audit logging Signed-off-by: Maciej Mierzwa <dev.maciej.mierzwa@gmail.com> * Adds unit tests for restPathMatches method Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Cleans up TODOs Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Organizes demo users and roles for extension Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Address PR feedback Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Adds more comments Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * add privileges info Signed-off-by: Maciej Mierzwa <dev.maciej.mierzwa@gmail.com> * Makes whoami action a named route and fixes license header check Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Adds integ tests for whoami route Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Change permissions order in roles.yml Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Adds developer documentation for authorization in REST layer Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes broken tests Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes checkstyle errors Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Addresses feedback and cleans up logic for super admin check Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Addresses Plugin Install CI failure Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Fixes failing citest task Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Modifies WhoAmI integ tests Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Adds a new endpoint called whoamiprotected and removes changes made to whoami route Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Updates documentation to reflect the new API Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Addresses PR feedback Signed-off-by: Darshit Chanpura <dchanp@amazon.com> * Renames action0 to actions Signed-off-by: Darshit Chanpura <dchanp@amazon.com> --------- Signed-off-by: Craig Perkins <cwperx@amazon.com> Signed-off-by: Darshit Chanpura <dchanp@amazon.com> Signed-off-by: Maciej Mierzwa <dev.maciej.mierzwa@gmail.com> Co-authored-by: Craig Perkins <cwperx@amazon.com> Co-authored-by: MaciejMierzwa <dev.maciej.mierzwa@gmail.com>
1 parent 49cbf52 commit a53a8a6

14 files changed

Lines changed: 795 additions & 24 deletions

File tree

DEVELOPER_GUIDE.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ So you want to contribute code to OpenSearch Security? Excellent! We're glad you
1010
- [Running integration tests](#running-integration-tests)
1111
- [Bulk test runs](#bulk-test-runs)
1212
- [Checkstyle Violations](#checkstyle-violations)
13+
- [Authorization in REST Layer](#authorization-in-rest-layer)
1314
- [Submitting Changes](#submitting-changes)
1415
- [Backports](#backports)
1516

@@ -78,6 +79,51 @@ mv config/* $OPENSEARCH_HOME/config/opensearch-security/
7879
rm -rf config/
7980
```
8081

82+
### Installing demo extension users and roles
83+
84+
If you are working with an extension and want to set up demo users for the Hello-World extension, append following items to files inside `$OPENSEARCH_HOME/config/opensearch-security/`:
85+
1. In **internal_users.yml**
86+
```yaml
87+
hw-user:
88+
hash: "$2a$12$VcCDgh2NDk07JGN0rjGbM.Ad41qVR/YFJcgHp0UGns5JDymv..TOG"
89+
reserved: true
90+
description: "Demo user for ext-test"
91+
```
92+
93+
2. In **roles.yml**
94+
```yaml
95+
extension_hw_greet:
96+
reserved: true
97+
cluster_permissions:
98+
- 'hw:greet'
99+
100+
extension_hw_full:
101+
reserved: true
102+
cluster_permissions:
103+
- 'hw:goodbye'
104+
- 'hw:greet'
105+
- 'hw:greet_with_adjective'
106+
- 'hw:greet_with_name'
107+
108+
legacy_hw_greet_with_name:
109+
reserved: true
110+
cluster_permissions:
111+
- 'cluster:admin/opensearch/hw/greet_with_name'
112+
```
113+
114+
3. In **roles_mapping.yml**
115+
```yaml
116+
legacy_hw_greet_with_name:
117+
reserved: true
118+
users:
119+
- "hw-user"
120+
121+
extension_hw_greet:
122+
reserved: true
123+
users:
124+
- "hw-user"
125+
```
126+
81127
To install the demo certificates and default configuration, answer `y` to the first two questions and `n` to the last one. The log should look like below:
82128

83129
```bash
@@ -188,6 +234,11 @@ Checkstyle enforces several rules within this codebase. Sometimes it will be nec
188234
// CS-ENFORCE-ALL
189235
```
190236
237+
## Authorization in REST Layer
238+
239+
See [REST_AUTHZ_FOR_PLUGINS](REST_AUTHZ_FOR_PLUGINS.md).
240+
241+
191242
## Submitting Changes
192243
193244
See [CONTRIBUTING](CONTRIBUTING.md).

REST_AUTHZ_FOR_PLUGINS.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Authorization at REST Layer for plugins
2+
3+
This feature is introduced as an added layer of security on top of existing TransportLayer authorization framework. In order to leverage these feature some core changes need to be made at Route registration level. This document talks about how you can achieve this.
4+
5+
**NOTE:** This doesn't replace Transport Layer Authorization. Plugin developers may choose to skip creating transport actions for APIs that do not need interaction with the Transport Layer.
6+
7+
## Pre-requisites
8+
9+
The security plugin must be installed and operational in your OpenSearch cluster for this feature to work.
10+
11+
### How does NamedRoute authorization work?
12+
13+
Once the routes are defined as NamedRoute, they, along-with their handlers, will be registered the same way as Route objects. When a request comes in, `SecurityRestFilter.java` applies an authorization check which extracts information about the NamedRoute.
14+
Next we get the unique name and actionNames associated with that route and evaluate these against existing `cluster_permissions` across all roles of the requesting user. If the authorization check succeeds, the request chain proceeds as normal. If it fails, a 401 response is returned to the user.
15+
16+
NOTE:
17+
1. The action names defined in roles must exactly match the names of registered routes, or else, the request would be deemed unauthorized.
18+
2. This check will not be implemented for plugins who do not use NamedRoutes.
19+
20+
21+
22+
### How to translate an existing Route to be a NamedRoute?
23+
24+
Here is a sample of an existing route converted to a named route:
25+
Before:
26+
```
27+
public List<Route> routes() {
28+
return ImmutableList.of(
29+
new Route(GET, "/uri")
30+
);
31+
}
32+
```
33+
With new scheme:
34+
```
35+
public List<NamedRoute> routes() {
36+
return ImmutableList.of(
37+
new NamedRoute.Builder().method(GET).path("/uri").uniqueName("plugin:uri").actionNames(Set.of("cluster:admin/opensearch/plugin/uri")).build()
38+
);
39+
}
40+
```
41+
42+
`actionNames()` are optional. They correspond to any current actions defined as permissions in roles.
43+
Ensure that these name-to-route mappings are easily accessible to the cluster admins to allow granting access to these APIs.
44+
45+
### How does authorization in the REST Layer work?
46+
47+
We will continue on the above example of translating `/uri` from Route to NamedRoute.
48+
49+
Consider these roles are defined in the cluster:
50+
```yaml
51+
plugin_role:
52+
reserved: true
53+
cluster_permissions:
54+
- 'plugin:uri'
55+
56+
plugin_role_legacy:
57+
reserved: true
58+
cluster_permissions:
59+
- 'cluster:admin/opensearch/plugin/uri'
60+
```
61+
62+
Successful authz scenarios for a user:
63+
1. The user is mapped either to `plugin_role` OR `plugin_role_legacy`.
64+
2. The user is mapped to both of these roles.
65+
3. The user is mapped to `plugin_role` even if no `actionNames()` were registered for this route.
66+
67+
Unsuccessful authz scenarios for a user:
68+
1. The user is not mapped any roles.
69+
2. The user is mapped to a different role which doesn't grant the cluster permissions: `plugin:uri` OR `cluster:admin/opensearch/plugin/uri`/
70+
3. The user is mapped to a role `plugin_role_other` which has a typo in action name, i.e.`plugin:uuri`.
71+
72+
73+
### Sample API in Security Plugin
74+
75+
As part of this effort a new uri `GET /whoamiprotected` was introduced as a NamedRoute version of `GET /whoami`. Here is how you can test it:
76+
77+
#### roles.yml
78+
```yaml
79+
who_am_i_role:
80+
reserved: true
81+
cluster_permissions:
82+
- 'security:whoamiprotected'
83+
84+
who_am_i_role_legacy:
85+
reserved: true
86+
cluster_permissions:
87+
- 'cluster:admin/opendistro_security/whoamiprotected'
88+
89+
who_am_i_role_no_perm:
90+
reserved: true
91+
cluster_permissions:
92+
- 'some_invalid_perm'
93+
94+
```
95+
96+
#### internal_users.yml
97+
```yaml
98+
who_am_i-user:
99+
hash: "$2a$12$VcCDgh2NDk07JGN0rjGbM.Ad41qVR/YFJcgHp0UGns5JDymv..TOG" #admin
100+
reserved: true
101+
description: "Demo user for ext-test"
102+
103+
who_am_i_legacy-user:
104+
hash: "$2a$12$VcCDgh2NDk07JGN0rjGbM.Ad41qVR/YFJcgHp0UGns5JDymv..TOG"
105+
reserved: true
106+
description: "Demo user for ext-test"
107+
108+
who_am_i_no_perm-user:
109+
hash: "$2a$12$VcCDgh2NDk07JGN0rjGbM.Ad41qVR/YFJcgHp0UGns5JDymv..TOG"
110+
reserved: true
111+
description: "Demo user for ext-test"
112+
```
113+
114+
#### roles_mapping.yml
115+
```yaml
116+
who_am_i_role:
117+
reserved: true
118+
users:
119+
- "who_am_i-user"
120+
121+
who_am_i_role_legacy:
122+
reserved: true
123+
users:
124+
- "who_am_i_legacy-user"
125+
126+
who_am_i_role_no_perm:
127+
reserved: true
128+
users:
129+
- "who_am_i_no_perm-user"
130+
```
131+
132+
Follow [DEVELOPER_GUIDE](DEVELOPER_GUIDE.md) to setup OpenSearch cluster and initialize security plugin. Once you have verified that security plugin is installed correctly and OpenSearch is running, execute following curl requests:
133+
1. `curl -XGET https://who_am_i-user:admin@localhost:9200/_plugins/_security/whoami --insecure` should succeed.
134+
2. `curl -XGET https://who_am_i_legacy-user:admin@localhost:9200/_plugins/_security/whoami --insecure` should succeed.
135+
3. `curl -XGET https://who_am_i_no-perm-user:admin@localhost:9200/_plugins/_security/whoami --insecure` should fail.
136+
4. `curl -XPOST ` to `/whoami` with all 3 users should succeed. This is because POST route is not a NamedRoute and hence no authorization check was made.
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*
8+
* Modifications Copyright OpenSearch Contributors. See
9+
* GitHub history for details.
10+
*/
11+
12+
package org.opensearch.security.rest;
13+
14+
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
15+
import org.apache.hc.core5.http.HttpStatus;
16+
import org.junit.ClassRule;
17+
import org.junit.Test;
18+
import org.junit.runner.RunWith;
19+
import org.opensearch.test.framework.TestSecurityConfig;
20+
import org.opensearch.test.framework.TestSecurityConfig.Role;
21+
import org.opensearch.test.framework.cluster.ClusterManager;
22+
import org.opensearch.test.framework.cluster.LocalCluster;
23+
import org.opensearch.test.framework.cluster.TestRestClient;
24+
25+
import static org.hamcrest.MatcherAssert.assertThat;
26+
import static org.hamcrest.Matchers.equalTo;
27+
import static org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.AUTHC_HTTPBASIC_INTERNAL;
28+
29+
@RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class)
30+
@ThreadLeakScope(ThreadLeakScope.Scope.NONE)
31+
public class WhoAmITests {
32+
protected final static TestSecurityConfig.User WHO_AM_I = new TestSecurityConfig.User("who_am_i_user").roles(
33+
new Role("who_am_i_role").clusterPermissions("security:whoamiprotected")
34+
);
35+
36+
protected final static TestSecurityConfig.User WHO_AM_I_LEGACY = new TestSecurityConfig.User("who_am_i_user_legacy").roles(
37+
new Role("who_am_i_role_legacy").clusterPermissions("cluster:admin/opendistro_security/whoamiprotected")
38+
);
39+
40+
protected final static TestSecurityConfig.User WHO_AM_I_NO_PERM = new TestSecurityConfig.User("who_am_i_user_no_perm").roles(
41+
new Role("who_am_i_role_no_perm")
42+
);
43+
44+
protected final static TestSecurityConfig.User WHO_AM_I_UNREGISTERED = new TestSecurityConfig.User("who_am_i_user_no_perm");
45+
46+
public static final String WHOAMI_ENDPOINT = "_plugins/_security/whoami";
47+
public static final String WHOAMI_PROTECTED_ENDPOINT = "_plugins/_security/whoamiprotected";
48+
49+
@ClassRule
50+
public static LocalCluster cluster = new LocalCluster.Builder().clusterManager(ClusterManager.THREE_CLUSTER_MANAGERS)
51+
.authc(AUTHC_HTTPBASIC_INTERNAL)
52+
.users(WHO_AM_I, WHO_AM_I_LEGACY, WHO_AM_I_NO_PERM)
53+
.build();
54+
55+
@Test
56+
public void testWhoAmIWithGetPermissions() throws Exception {
57+
try (TestRestClient client = cluster.getRestClient(WHO_AM_I)) {
58+
assertThat(client.get(WHOAMI_PROTECTED_ENDPOINT).getStatusCode(), equalTo(HttpStatus.SC_OK));
59+
}
60+
61+
try (TestRestClient client = cluster.getRestClient(WHO_AM_I)) {
62+
assertThat(client.get(WHOAMI_ENDPOINT).getStatusCode(), equalTo(HttpStatus.SC_OK));
63+
}
64+
}
65+
66+
@Test
67+
public void testWhoAmIWithGetPermissionsLegacy() throws Exception {
68+
try (TestRestClient client = cluster.getRestClient(WHO_AM_I_LEGACY)) {
69+
assertThat(client.get(WHOAMI_ENDPOINT).getStatusCode(), equalTo(HttpStatus.SC_OK));
70+
}
71+
72+
try (TestRestClient client = cluster.getRestClient(WHO_AM_I_LEGACY)) {
73+
assertThat(client.get(WHOAMI_PROTECTED_ENDPOINT).getStatusCode(), equalTo(HttpStatus.SC_OK));
74+
}
75+
}
76+
77+
@Test
78+
public void testWhoAmIWithoutGetPermissions() throws Exception {
79+
try (TestRestClient client = cluster.getRestClient(WHO_AM_I_NO_PERM)) {
80+
assertThat(client.get(WHOAMI_ENDPOINT).getStatusCode(), equalTo(HttpStatus.SC_OK));
81+
}
82+
83+
try (TestRestClient client = cluster.getRestClient(WHO_AM_I_NO_PERM)) {
84+
assertThat(client.get(WHOAMI_PROTECTED_ENDPOINT).getStatusCode(), equalTo(HttpStatus.SC_UNAUTHORIZED));
85+
}
86+
}
87+
88+
@Test
89+
public void testWhoAmIPost() throws Exception {
90+
try (TestRestClient client = cluster.getRestClient(WHO_AM_I)) {
91+
assertThat(client.post(WHOAMI_ENDPOINT).getStatusCode(), equalTo(HttpStatus.SC_OK));
92+
}
93+
94+
try (TestRestClient client = cluster.getRestClient(WHO_AM_I_LEGACY)) {
95+
assertThat(client.post(WHOAMI_ENDPOINT).getStatusCode(), equalTo(HttpStatus.SC_OK));
96+
}
97+
98+
try (TestRestClient client = cluster.getRestClient(WHO_AM_I_NO_PERM)) {
99+
assertThat(client.post(WHOAMI_ENDPOINT).getStatusCode(), equalTo(HttpStatus.SC_OK));
100+
}
101+
102+
try (TestRestClient client = cluster.getRestClient(WHO_AM_I_UNREGISTERED)) {
103+
assertThat(client.post(WHOAMI_ENDPOINT).getStatusCode(), equalTo(HttpStatus.SC_OK));
104+
}
105+
106+
}
107+
}

src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
import org.opensearch.security.http.XFFResolver;
147147
import org.opensearch.security.privileges.PrivilegesEvaluator;
148148
import org.opensearch.security.privileges.PrivilegesInterceptor;
149+
import org.opensearch.security.privileges.RestLayerPrivilegesEvaluator;
149150
import org.opensearch.security.resolver.IndexResolverReplacer;
150151
import org.opensearch.security.rest.DashboardsInfoAction;
151152
import org.opensearch.security.rest.SecurityConfigUpdateAction;
@@ -205,6 +206,7 @@ public final class OpenSearchSecurityPlugin extends OpenSearchSecuritySSLPlugin
205206
private volatile SecurityInterceptor si;
206207
private volatile PrivilegesEvaluator evaluator;
207208
private volatile UserService userService;
209+
private volatile RestLayerPrivilegesEvaluator restLayerEvaluator;
208210
private volatile ThreadPool threadPool;
209211
private volatile ConfigurationRepository cr;
210212
private volatile AdminDNs adminDns;
@@ -1019,8 +1021,11 @@ public Collection<Object> createComponents(
10191021
principalExtractor = ReflectionHelper.instantiatePrincipalExtractor(principalExtractorClass);
10201022
}
10211023

1024+
restLayerEvaluator = new RestLayerPrivilegesEvaluator(clusterService, threadPool, auditLog, cih, namedXContentRegistry);
1025+
10221026
securityRestHandler = new SecurityRestFilter(
10231027
backendRegistry,
1028+
restLayerEvaluator,
10241029
auditLog,
10251030
threadPool,
10261031
principalExtractor,
@@ -1035,6 +1040,7 @@ public Collection<Object> createComponents(
10351040
dcf.registerDCFListener(irr);
10361041
dcf.registerDCFListener(xffResolver);
10371042
dcf.registerDCFListener(evaluator);
1043+
dcf.registerDCFListener(restLayerEvaluator);
10381044
dcf.registerDCFListener(securityRestHandler);
10391045
if (!(auditLog instanceof NullAuditLog)) {
10401046
// Don't register if advanced modules is disabled in which case auditlog is instance of NullAuditLog
@@ -1072,6 +1078,7 @@ public Collection<Object> createComponents(
10721078
components.add(xffResolver);
10731079
components.add(backendRegistry);
10741080
components.add(evaluator);
1081+
components.add(restLayerEvaluator);
10751082
components.add(si);
10761083
components.add(dcf);
10771084
components.add(userService);

src/main/java/org/opensearch/security/auditlog/impl/AbstractAuditLog.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ public void logMissingPrivileges(String privilege, String effectiveUser, RestReq
184184
msg.addRemoteAddress(remoteAddress);
185185
msg.addRestRequestInfo(request, auditConfigFilter);
186186
msg.addEffectiveUser(effectiveUser);
187+
msg.addPrivilege(privilege);
187188
save(msg);
188189
}
189190

src/main/java/org/opensearch/security/dlic/rest/support/Utils.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.opensearch.core.xcontent.NamedXContentRegistry;
4545
import org.opensearch.core.xcontent.ToXContent;
4646
import org.opensearch.core.xcontent.XContentParser;
47+
import org.opensearch.rest.NamedRoute;
4748
import org.opensearch.rest.RestHandler.DeprecatedRoute;
4849
import org.opensearch.rest.RestHandler.Route;
4950
import org.opensearch.security.DefaultObjectMapper;
@@ -240,9 +241,17 @@ public static List<Route> addRoutesPrefix(List<Route> routes) {
240241
* Total number of routes will be expanded len(prefixes) as much comparing to the list passed in
241242
*/
242243
public static List<Route> addRoutesPrefix(List<Route> routes, final String... prefixes) {
243-
return routes.stream()
244-
.flatMap(r -> Arrays.stream(prefixes).map(p -> new Route(r.getMethod(), p + r.getPath())))
245-
.collect(ImmutableList.toImmutableList());
244+
return routes.stream().flatMap(r -> Arrays.stream(prefixes).map(p -> {
245+
if (r instanceof NamedRoute) {
246+
NamedRoute nr = (NamedRoute) r;
247+
return new NamedRoute.Builder().method(nr.getMethod())
248+
.path(p + nr.getPath())
249+
.uniqueName(nr.name())
250+
.legacyActionNames(nr.actionNames())
251+
.build();
252+
}
253+
return new Route(r.getMethod(), p + r.getPath());
254+
})).collect(ImmutableList.toImmutableList());
246255
}
247256

248257
/**

0 commit comments

Comments
 (0)