19
19
import org .elasticsearch .entitlement .runtime .policy .entitlements .CreateClassLoaderEntitlement ;
20
20
import org .elasticsearch .entitlement .runtime .policy .entitlements .ExitVMEntitlement ;
21
21
import org .elasticsearch .entitlement .runtime .policy .entitlements .FilesEntitlement ;
22
+ import org .elasticsearch .entitlement .runtime .policy .entitlements .OutboundNetworkEntitlement ;
22
23
import org .elasticsearch .test .ESTestCase ;
23
24
import org .elasticsearch .test .compiler .InMemoryJavaCompiler ;
24
25
import org .elasticsearch .test .jar .JarUtils ;
31
32
import java .net .URL ;
32
33
import java .net .URLClassLoader ;
33
34
import java .nio .file .Path ;
34
- import java .util .Arrays ;
35
35
import java .util .List ;
36
36
import java .util .Map ;
37
37
import java .util .Set ;
38
+ import java .util .concurrent .atomic .AtomicReference ;
38
39
import java .util .stream .Stream ;
39
40
40
41
import static java .util .Map .entry ;
41
- import static org .elasticsearch .entitlement .runtime .policy .PolicyManager .ALL_UNNAMED ;
42
42
import static org .elasticsearch .entitlement .runtime .policy .PolicyManager .ComponentKind .SERVER ;
43
- import static org .hamcrest .Matchers .aMapWithSize ;
44
43
import static org .hamcrest .Matchers .allOf ;
45
44
import static org .hamcrest .Matchers .containsString ;
46
45
import static org .hamcrest .Matchers .is ;
47
- import static org .hamcrest .Matchers .sameInstance ;
48
46
49
47
@ ESTestCase .WithoutSecurityManager
50
48
public class PolicyManagerTests extends ESTestCase {
@@ -89,223 +87,81 @@ public static void beforeClass() {
89
87
}
90
88
}
91
89
92
- public void testGetEntitlementsThrowsOnMissingPluginUnnamedModule () {
93
- var plugin1SourcePath = Path .of ("modules" , "plugin1" );
94
- var policyManager = new PolicyManager (
95
- createEmptyTestServerPolicy (),
96
- List .of (),
97
- Map .of ("plugin1" , createPluginPolicy ("plugin.module" )),
98
- c -> PolicyScope .plugin ("plugin1" , moduleName (c )),
99
- Map .of ("plugin1" , plugin1SourcePath ),
100
- NO_ENTITLEMENTS_MODULE ,
101
- TEST_PATH_LOOKUP ,
102
- Set .of ()
103
- );
104
-
105
- // Any class from the current module (unnamed) will do
106
- var callerClass = this .getClass ();
107
- var requestingModule = callerClass .getModule ();
108
-
109
- assertEquals (
110
- "No policy for the unnamed module" ,
111
- policyManager .defaultEntitlements ("plugin1" , plugin1SourcePath , requestingModule .getName ()),
112
- policyManager .getEntitlements (callerClass )
113
- );
114
-
115
- assertEquals (
116
- Map .of (requestingModule , policyManager .defaultEntitlements ("plugin1" , plugin1SourcePath , requestingModule .getName ())),
117
- policyManager .moduleEntitlementsMap
118
- );
119
- }
120
-
121
- public void testGetEntitlementsThrowsOnMissingPolicyForPlugin () {
122
- var plugin1SourcePath = Path .of ("modules" , "plugin1" );
123
- var policyManager = new PolicyManager (
124
- createEmptyTestServerPolicy (),
125
- List .of (),
126
- Map .of (),
127
- c -> PolicyScope .plugin ("plugin1" , moduleName (c )),
128
- Map .of ("plugin1" , plugin1SourcePath ),
129
- NO_ENTITLEMENTS_MODULE ,
130
- TEST_PATH_LOOKUP ,
131
- Set .of ()
132
- );
133
-
134
- // Any class from the current module (unnamed) will do
135
- var callerClass = this .getClass ();
136
- var requestingModule = callerClass .getModule ();
137
-
138
- assertEquals (
139
- "No policy for this plugin" ,
140
- policyManager .defaultEntitlements ("plugin1" , plugin1SourcePath , requestingModule .getName ()),
141
- policyManager .getEntitlements (callerClass )
142
- );
90
+ public void testGetEntitlements () {
91
+ // A mutable policyScope we can use to program specific replies
92
+ AtomicReference <PolicyScope > policyScope = new AtomicReference <>();
143
93
144
- assertEquals (
145
- Map .of (requestingModule , policyManager .defaultEntitlements ("plugin1" , plugin1SourcePath , requestingModule .getName ())),
146
- policyManager .moduleEntitlementsMap
147
- );
148
- }
149
-
150
- public void testGetEntitlementsFailureIsCached () {
94
+ // A common policy with a variety of entitlements to test
95
+ Path thisSourcePath = PolicyManager .getComponentPathFromClass (getClass ());
151
96
var plugin1SourcePath = Path .of ("modules" , "plugin1" );
152
97
var policyManager = new PolicyManager (
153
- createEmptyTestServerPolicy ( ),
98
+ new Policy ( "server" , List . of ( new Scope ( "org.example.httpclient" , List . of ( new OutboundNetworkEntitlement ()))) ),
154
99
List .of (),
155
- Map .of (),
156
- c -> PolicyScope . plugin ( "plugin1" , moduleName ( c ) ),
100
+ Map .of ("plugin1" , new Policy ( "plugin1" , List . of ( new Scope ( "plugin.module1" , List . of ( new ExitVMEntitlement ())))) ),
101
+ c -> policyScope . get ( ),
157
102
Map .of ("plugin1" , plugin1SourcePath ),
158
103
NO_ENTITLEMENTS_MODULE ,
159
104
TEST_PATH_LOOKUP ,
160
105
Set .of ()
161
106
);
162
107
163
- // Any class from the current module (unnamed) will do
164
- var callerClass = this .getClass ();
165
- var requestingModule = callerClass .getModule ();
108
+ // "Unspecified" below means that the module is not named in the policy
166
109
167
- assertEquals (
168
- policyManager .defaultEntitlements ("plugin1" , plugin1SourcePath , requestingModule .getName ()),
169
- policyManager .getEntitlements (callerClass )
170
- );
171
- assertEquals (
172
- Map .of (requestingModule , policyManager .defaultEntitlements ("plugin1" , plugin1SourcePath , requestingModule .getName ())),
173
- policyManager .moduleEntitlementsMap
110
+ policyScope .set (PolicyScope .server ("org.example.httpclient" ));
111
+ resetAndCheckEntitlements (
112
+ "Specified entitlements for server" ,
113
+ getClass (),
114
+ policyManager .policyEntitlements (
115
+ SERVER .componentName ,
116
+ thisSourcePath ,
117
+ "org.example.httpclient" ,
118
+ List .of (new OutboundNetworkEntitlement ())
119
+ ),
120
+ policyManager
174
121
);
175
122
176
- // A second time
177
- assertEquals (
178
- policyManager .defaultEntitlements ("plugin1" , plugin1SourcePath , requestingModule .getName ()),
179
- policyManager .getEntitlements (callerClass )
123
+ policyScope .set (PolicyScope .server ("plugin.unspecifiedModule" ));
124
+ resetAndCheckEntitlements (
125
+ "Default entitlements for unspecified module" ,
126
+ getClass (),
127
+ policyManager .defaultEntitlements (SERVER .componentName , thisSourcePath , "plugin.unspecifiedModule" ),
128
+ policyManager
180
129
);
181
130
182
- // Nothing new in the map
183
- assertEquals (
184
- Map .of (requestingModule , policyManager .defaultEntitlements ("plugin1" , plugin1SourcePath , requestingModule .getName ())),
185
- policyManager .moduleEntitlementsMap
131
+ policyScope .set (PolicyScope .plugin ("plugin1" , "plugin.module1" ));
132
+ resetAndCheckEntitlements (
133
+ "Specified entitlements for plugin" ,
134
+ getClass (),
135
+ policyManager .policyEntitlements ("plugin1" , plugin1SourcePath , "plugin.module1" , List .of (new ExitVMEntitlement ())),
136
+ policyManager
186
137
);
187
- }
188
138
189
- public void testGetEntitlementsReturnsEntitlementsForPluginUnnamedModule () {
190
- var policyManager = new PolicyManager (
191
- createEmptyTestServerPolicy (),
192
- List .of (),
193
- Map .ofEntries (entry ("plugin2" , createPluginPolicy (ALL_UNNAMED ))),
194
- c -> PolicyScope .plugin ("plugin2" , moduleName (c )),
195
- Map .of ("plugin2" , Path .of ("modules" , "plugin2" )),
196
- NO_ENTITLEMENTS_MODULE ,
197
- TEST_PATH_LOOKUP ,
198
- Set .of ()
139
+ policyScope .set (PolicyScope .plugin ("plugin1" , "plugin.unspecifiedModule" ));
140
+ resetAndCheckEntitlements (
141
+ "Default entitlements for plugin" ,
142
+ getClass (),
143
+ policyManager .defaultEntitlements ("plugin1" , plugin1SourcePath , "plugin.unspecifiedModule" ),
144
+ policyManager
199
145
);
200
-
201
- // Any class from the current module (unnamed) will do
202
- var callerClass = this .getClass ();
203
-
204
- var entitlements = policyManager .getEntitlements (callerClass );
205
- assertThat (entitlements .hasEntitlement (CreateClassLoaderEntitlement .class ), is (true ));
206
146
}
207
147
208
- public void testGetEntitlementsReturnsDefaultOnMissingPolicyForServer () throws ClassNotFoundException {
209
- var policyManager = new PolicyManager (
210
- createTestServerPolicy ("example" ),
211
- List .of (),
212
- Map .of (),
213
- c -> PolicyScope .server (moduleName (c )),
214
- Map .of (),
215
- NO_ENTITLEMENTS_MODULE ,
216
- TEST_PATH_LOOKUP ,
217
- Set .of ()
218
- );
219
-
220
- // Any class will do, since our resolver is hardcoded to use SERVER_COMPONENT_NAME.
221
- // Let's pick one with a known module name.
222
- String httpserverModuleName = "jdk.httpserver" ;
223
- var mockServerClass = ModuleLayer .boot ().findLoader (httpserverModuleName ).loadClass ("com.sun.net.httpserver.HttpServer" );
224
- var mockServerSourcePath = PolicyManager .getComponentPathFromClass (mockServerClass );
225
- var requestingModule = mockServerClass .getModule ();
226
-
148
+ private void resetAndCheckEntitlements (
149
+ String message ,
150
+ Class <?> requestingClass ,
151
+ ModuleEntitlements expectedEntitlements ,
152
+ PolicyManager policyManager
153
+ ) {
154
+ policyManager .moduleEntitlementsMap .clear ();
155
+ assertEquals (message , expectedEntitlements , policyManager .getEntitlements (requestingClass ));
227
156
assertEquals (
228
- "No policy for this module in server" ,
229
- policyManager .defaultEntitlements (SERVER .componentName , mockServerSourcePath , httpserverModuleName ),
230
- policyManager .getEntitlements (mockServerClass )
231
- );
232
-
233
- assertEquals (
234
- Map .of (requestingModule , policyManager .defaultEntitlements (SERVER .componentName , mockServerSourcePath , httpserverModuleName )),
157
+ "Map has precisely the one expected entry" ,
158
+ Map .of (requestingClass .getModule (), expectedEntitlements ),
235
159
policyManager .moduleEntitlementsMap
236
160
);
237
- }
238
161
239
- public void testGetEntitlementsReturnsEntitlementsForServerModule () throws ClassNotFoundException {
240
- String httpserverModuleName = "jdk.httpserver" ;
241
- var policyManager = new PolicyManager (
242
- createTestServerPolicy (httpserverModuleName ),
243
- List .of (),
244
- Map .of (),
245
- c -> PolicyScope .server (moduleName (c )),
246
- Map .of (),
247
- NO_ENTITLEMENTS_MODULE ,
248
- TEST_PATH_LOOKUP ,
249
- Set .of ()
250
- );
251
-
252
- // Any class will do, since our resolver is hardcoded to use SERVER_COMPONENT_NAME.
253
- // Let's pick one with a known module name.
254
- var mockServerClass = ModuleLayer .boot ().findLoader (httpserverModuleName ).loadClass ("com.sun.net.httpserver.HttpServer" );
255
-
256
- var entitlements = policyManager .getEntitlements (mockServerClass );
257
- assertThat (entitlements .hasEntitlement (CreateClassLoaderEntitlement .class ), is (true ));
258
- assertThat (entitlements .hasEntitlement (ExitVMEntitlement .class ), is (true ));
259
- }
260
-
261
- public void testGetEntitlementsReturnsEntitlementsForPluginModule () throws IOException , ClassNotFoundException {
262
- final Path home = createTempDir ();
263
-
264
- Path jar = createMockPluginJar (home );
265
-
266
- var policyManager = new PolicyManager (
267
- createEmptyTestServerPolicy (),
268
- List .of (),
269
- Map .of ("mock-plugin" , createPluginPolicy ("org.example.plugin" )),
270
- c -> PolicyScope .plugin ("mock-plugin" , moduleName (c )),
271
- Map .of ("mock-plugin" , Path .of ("modules" , "mock-plugin" )),
272
- NO_ENTITLEMENTS_MODULE ,
273
- TEST_PATH_LOOKUP ,
274
- Set .of ()
275
- );
276
-
277
- var layer = createLayerForJar (jar , "org.example.plugin" );
278
- var mockPluginClass = layer .findLoader ("org.example.plugin" ).loadClass ("q.B" );
279
-
280
- var entitlements = policyManager .getEntitlements (mockPluginClass );
281
- assertThat (entitlements .hasEntitlement (CreateClassLoaderEntitlement .class ), is (true ));
282
- assertThat (entitlements .fileAccess ().canRead (TEST_BASE_DIR ), is (true ));
283
- }
284
-
285
- public void testGetEntitlementsResultIsCached () {
286
- var policyManager = new PolicyManager (
287
- createEmptyTestServerPolicy (),
288
- List .of (),
289
- Map .ofEntries (entry ("plugin2" , createPluginPolicy (ALL_UNNAMED ))),
290
- c -> PolicyScope .plugin ("plugin2" , moduleName (c )),
291
- Map .of ("plugin2" , Path .of ("modules" , "plugin2" )),
292
- NO_ENTITLEMENTS_MODULE ,
293
- TEST_PATH_LOOKUP ,
294
- Set .of ()
295
- );
296
-
297
- // Any class from the current module (unnamed) will do
298
- var callerClass = this .getClass ();
299
-
300
- var entitlements = policyManager .getEntitlements (callerClass );
301
- assertThat (entitlements .hasEntitlement (CreateClassLoaderEntitlement .class ), is (true ));
302
- assertThat (policyManager .moduleEntitlementsMap , aMapWithSize (1 ));
303
- var cachedResult = policyManager .moduleEntitlementsMap .values ().stream ().findFirst ().orElseThrow ();
304
- var entitlementsAgain = policyManager .getEntitlements (callerClass );
305
-
306
- // Nothing new in the map
307
- assertThat (policyManager .moduleEntitlementsMap , aMapWithSize (1 ));
308
- assertThat (entitlementsAgain , sameInstance (cachedResult ));
162
+ // Fetch a second time and verify the map is unchanged
163
+ policyManager .getEntitlements (requestingClass );
164
+ assertEquals ("Map is unchanged" , Map .of (requestingClass .getModule (), expectedEntitlements ), policyManager .moduleEntitlementsMap );
309
165
}
310
166
311
167
public void testRequestingClassFastPath () throws IOException , ClassNotFoundException {
@@ -560,24 +416,6 @@ public void testFilesEntitlementsWithExclusive() {
560
416
);
561
417
}
562
418
563
- /**
564
- * If the plugin resolver tells us a class is in a plugin, don't conclude that it's in an agent.
565
- */
566
- public void testPluginResolverOverridesAgents () {
567
- var policyManager = new PolicyManager (
568
- createEmptyTestServerPolicy (),
569
- List .of (new CreateClassLoaderEntitlement ()),
570
- Map .of (),
571
- c -> PolicyScope .plugin ("test" , moduleName (c )), // Insist that the class is in a plugin
572
- Map .of (),
573
- NO_ENTITLEMENTS_MODULE ,
574
- TEST_PATH_LOOKUP ,
575
- Set .of ()
576
- );
577
- ModuleEntitlements notAgentsEntitlements = policyManager .getEntitlements (TestAgent .class );
578
- assertThat (notAgentsEntitlements .hasEntitlement (CreateClassLoaderEntitlement .class ), is (false ));
579
- }
580
-
581
419
private static Class <?> makeClassInItsOwnModule () throws IOException , ClassNotFoundException {
582
420
final Path home = createTempDir ();
583
421
Path jar = createMockPluginJar (home );
@@ -602,27 +440,6 @@ private static Policy createEmptyTestServerPolicy() {
602
440
return new Policy ("server" , List .of ());
603
441
}
604
442
605
- private static Policy createTestServerPolicy (String scopeName ) {
606
- return new Policy ("server" , List .of (new Scope (scopeName , List .of (new ExitVMEntitlement (), new CreateClassLoaderEntitlement ()))));
607
- }
608
-
609
- private static Policy createPluginPolicy (String ... pluginModules ) {
610
- return new Policy (
611
- "plugin" ,
612
- Arrays .stream (pluginModules )
613
- .map (
614
- name -> new Scope (
615
- name ,
616
- List .of (
617
- new FilesEntitlement (List .of (FilesEntitlement .FileData .ofPath (TEST_BASE_DIR , FilesEntitlement .Mode .READ ))),
618
- new CreateClassLoaderEntitlement ()
619
- )
620
- )
621
- )
622
- .toList ()
623
- );
624
- }
625
-
626
443
private static Path createMockPluginJarForUnnamedModule (Path home ) throws IOException {
627
444
Path jar = home .resolve ("unnamed-mock-plugin.jar" );
628
445
0 commit comments