59
59
import static java .util .zip .ZipFile .OPEN_READ ;
60
60
import static org .elasticsearch .entitlement .bridge .Util .NO_CLASS ;
61
61
import static org .elasticsearch .entitlement .runtime .policy .PathLookup .BaseDir .TEMP ;
62
+ import static org .elasticsearch .entitlement .runtime .policy .PolicyManager .ComponentKind .APM_AGENT ;
63
+ import static org .elasticsearch .entitlement .runtime .policy .PolicyManager .ComponentKind .PLUGIN ;
64
+ import static org .elasticsearch .entitlement .runtime .policy .PolicyManager .ComponentKind .SERVER ;
65
+ import static org .elasticsearch .entitlement .runtime .policy .PolicyManager .ComponentKind .UNKNOWN ;
62
66
63
67
/**
64
68
* This class is responsible for finding the <strong>component</strong> (system, server, plugin, agent) for a caller class to check,
@@ -128,14 +132,55 @@ public class PolicyManager {
128
132
*/
129
133
private static final Logger generalLogger = LogManager .getLogger (PolicyManager .class );
130
134
131
- static final String UNKNOWN_COMPONENT_NAME = "(unknown)" ;
132
- static final String SERVER_COMPONENT_NAME = "(server)" ;
133
- static final String APM_AGENT_COMPONENT_NAME = "(APM agent)" ;
134
-
135
135
static final Class <?> DEFAULT_FILESYSTEM_CLASS = PathUtils .getDefaultFileSystem ().getClass ();
136
136
137
137
static final Set <String > MODULES_EXCLUDED_FROM_SYSTEM_MODULES = Set .of ("java.desktop" );
138
138
139
+ /**
140
+ * Identifies a particular entitlement {@link Scope} within a {@link Policy}.
141
+ */
142
+ public record PolicyScope (ComponentKind kind , String componentName , String moduleName ) {
143
+ public PolicyScope {
144
+ requireNonNull (kind );
145
+ requireNonNull (componentName );
146
+ requireNonNull (moduleName );
147
+ assert kind .componentName == null || kind .componentName .equals (componentName );
148
+ }
149
+
150
+ public static PolicyScope unknown (String moduleName ) {
151
+ return new PolicyScope (UNKNOWN , UNKNOWN .componentName , moduleName );
152
+ }
153
+
154
+ public static PolicyScope server (String moduleName ) {
155
+ return new PolicyScope (SERVER , SERVER .componentName , moduleName );
156
+ }
157
+
158
+ public static PolicyScope apmAgent (String moduleName ) {
159
+ return new PolicyScope (APM_AGENT , APM_AGENT .componentName , moduleName );
160
+ }
161
+
162
+ public static PolicyScope plugin (String componentName , String moduleName ) {
163
+ return new PolicyScope (PLUGIN , componentName , moduleName );
164
+ }
165
+ }
166
+
167
+ public enum ComponentKind {
168
+ UNKNOWN ("(unknown)" ),
169
+ SERVER ("(server)" ),
170
+ APM_AGENT ("(APM agent)" ),
171
+ PLUGIN (null );
172
+
173
+ /**
174
+ * If this kind corresponds to a single component, this is that component's name;
175
+ * otherwise null.
176
+ */
177
+ final String componentName ;
178
+
179
+ ComponentKind (String componentName ) {
180
+ this .componentName = componentName ;
181
+ }
182
+ }
183
+
139
184
/**
140
185
* This class contains all the entitlements by type, plus the {@link FileAccessTree} for the special case of filesystem entitlements.
141
186
* <p>
@@ -209,7 +254,7 @@ ModuleEntitlements policyEntitlements(String componentName, Path componentPath,
209
254
private final Map <String , List <Entitlement >> serverEntitlements ;
210
255
private final List <Entitlement > apmAgentEntitlements ;
211
256
private final Map <String , Map <String , List <Entitlement >>> pluginsEntitlements ;
212
- private final Function <Class <?>, String > pluginResolver ;
257
+ private final Function <Class <?>, PolicyScope > scopeResolver ;
213
258
private final PathLookup pathLookup ;
214
259
private final Set <Class <?>> mutedClasses ;
215
260
@@ -245,10 +290,6 @@ private static Set<Module> findSystemLayerModules() {
245
290
.collect (Collectors .toUnmodifiableSet ());
246
291
247
292
private final Map <String , Path > sourcePaths ;
248
- /**
249
- * The package name containing classes from the APM agent.
250
- */
251
- private final String apmAgentPackageName ;
252
293
253
294
/**
254
295
* Frames originating from this module are ignored in the permission logic.
@@ -266,9 +307,8 @@ public PolicyManager(
266
307
Policy serverPolicy ,
267
308
List <Entitlement > apmAgentEntitlements ,
268
309
Map <String , Policy > pluginPolicies ,
269
- Function <Class <?>, String > pluginResolver ,
310
+ Function <Class <?>, PolicyScope > scopeResolver ,
270
311
Map <String , Path > sourcePaths ,
271
- String apmAgentPackageName ,
272
312
Module entitlementsModule ,
273
313
PathLookup pathLookup ,
274
314
Set <Class <?>> suppressFailureLogClasses
@@ -278,18 +318,17 @@ public PolicyManager(
278
318
this .pluginsEntitlements = requireNonNull (pluginPolicies ).entrySet ()
279
319
.stream ()
280
320
.collect (toUnmodifiableMap (Map .Entry ::getKey , e -> buildScopeEntitlementsMap (e .getValue ())));
281
- this .pluginResolver = pluginResolver ;
321
+ this .scopeResolver = scopeResolver ;
282
322
this .sourcePaths = sourcePaths ;
283
- this .apmAgentPackageName = apmAgentPackageName ;
284
323
this .entitlementsModule = entitlementsModule ;
285
324
this .pathLookup = requireNonNull (pathLookup );
286
325
this .mutedClasses = suppressFailureLogClasses ;
287
326
288
327
List <ExclusiveFileEntitlement > exclusiveFileEntitlements = new ArrayList <>();
289
328
for (var e : serverEntitlements .entrySet ()) {
290
- validateEntitlementsPerModule (SERVER_COMPONENT_NAME , e .getKey (), e .getValue (), exclusiveFileEntitlements );
329
+ validateEntitlementsPerModule (SERVER . componentName , e .getKey (), e .getValue (), exclusiveFileEntitlements );
291
330
}
292
- validateEntitlementsPerModule (APM_AGENT_COMPONENT_NAME , ALL_UNNAMED , apmAgentEntitlements , exclusiveFileEntitlements );
331
+ validateEntitlementsPerModule (APM_AGENT . componentName , ALL_UNNAMED , apmAgentEntitlements , exclusiveFileEntitlements );
293
332
for (var p : pluginsEntitlements .entrySet ()) {
294
333
for (var m : p .getValue ().entrySet ()) {
295
334
validateEntitlementsPerModule (p .getKey (), m .getKey (), m .getValue (), exclusiveFileEntitlements );
@@ -684,50 +723,40 @@ ModuleEntitlements getEntitlements(Class<?> requestingClass) {
684
723
}
685
724
686
725
private ModuleEntitlements computeEntitlements (Class <?> requestingClass ) {
687
- Module requestingModule = requestingClass .getModule ();
688
- if (isServerModule (requestingModule )) {
689
- return getModuleScopeEntitlements (
690
- serverEntitlements ,
691
- requestingModule .getName (),
692
- SERVER_COMPONENT_NAME ,
693
- getComponentPathFromClass (requestingClass )
694
- );
695
- }
726
+ var policyScope = scopeResolver .apply (requestingClass );
727
+ var componentName = policyScope .componentName ();
728
+ var moduleName = policyScope .moduleName ();
696
729
697
- // plugins
698
- var pluginName = pluginResolver .apply (requestingClass );
699
- if (pluginName != null ) {
700
- var pluginEntitlements = pluginsEntitlements .get (pluginName );
701
- if (pluginEntitlements == null ) {
702
- return defaultEntitlements (pluginName , sourcePaths .get (pluginName ), requestingModule .getName ());
703
- } else {
730
+ switch (policyScope .kind ()) {
731
+ case SERVER -> {
704
732
return getModuleScopeEntitlements (
705
- pluginEntitlements ,
706
- getScopeName ( requestingModule ) ,
707
- pluginName ,
708
- sourcePaths . get ( pluginName )
733
+ serverEntitlements ,
734
+ moduleName ,
735
+ SERVER . componentName ,
736
+ getComponentPathFromClass ( requestingClass )
709
737
);
710
738
}
711
- }
712
-
713
- if (requestingModule .isNamed () == false && requestingClass .getPackageName ().startsWith (apmAgentPackageName )) {
714
- // The APM agent is the only thing running non-modular in the system classloader
715
- return policyEntitlements (
716
- APM_AGENT_COMPONENT_NAME ,
717
- getComponentPathFromClass (requestingClass ),
718
- ALL_UNNAMED ,
719
- apmAgentEntitlements
720
- );
721
- }
722
-
723
- return defaultEntitlements (UNKNOWN_COMPONENT_NAME , null , requestingModule .getName ());
724
- }
725
-
726
- private static String getScopeName (Module requestingModule ) {
727
- if (requestingModule .isNamed () == false ) {
728
- return ALL_UNNAMED ;
729
- } else {
730
- return requestingModule .getName ();
739
+ case APM_AGENT -> {
740
+ // The APM agent is the only thing running non-modular in the system classloader
741
+ return policyEntitlements (
742
+ APM_AGENT .componentName ,
743
+ getComponentPathFromClass (requestingClass ),
744
+ ALL_UNNAMED ,
745
+ apmAgentEntitlements
746
+ );
747
+ }
748
+ case UNKNOWN -> {
749
+ return defaultEntitlements (UNKNOWN .componentName , null , moduleName );
750
+ }
751
+ default -> {
752
+ assert policyScope .kind () == PLUGIN ;
753
+ var pluginEntitlements = pluginsEntitlements .get (componentName );
754
+ if (pluginEntitlements == null ) {
755
+ return defaultEntitlements (componentName , sourcePaths .get (componentName ), moduleName );
756
+ } else {
757
+ return getModuleScopeEntitlements (pluginEntitlements , moduleName , componentName , sourcePaths .get (componentName ));
758
+ }
759
+ }
731
760
}
732
761
}
733
762
@@ -763,10 +792,6 @@ private ModuleEntitlements getModuleScopeEntitlements(
763
792
return policyEntitlements (componentName , componentPath , scopeName , entitlements );
764
793
}
765
794
766
- private static boolean isServerModule (Module requestingModule ) {
767
- return requestingModule .isNamed () && requestingModule .getLayer () == ModuleLayer .boot ();
768
- }
769
-
770
795
/**
771
796
* Walks the stack to determine which class should be checked for entitlements.
772
797
*
0 commit comments