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