5050public class PolicyManager {
5151 private static final Logger logger = LogManager .getLogger (PolicyManager .class );
5252
53- record ModuleEntitlements (Map <Class <? extends Entitlement >, List <Entitlement >> entitlementsByType , FileAccessTree fileAccess ) {
54- public static final ModuleEntitlements NONE = new ModuleEntitlements (Map .of (), FileAccessTree .EMPTY );
53+ static final String UNKNOWN_COMPONENT_NAME = "(unknown)" ;
54+ static final String SERVER_COMPONENT_NAME = "(server)" ;
55+ static final String APM_AGENT_COMPONENT_NAME = "(APM agent)" ;
56+
57+ /**
58+ * @param componentName the plugin name; or else one of the special component names
59+ * like {@link #SERVER_COMPONENT_NAME} or {@link #APM_AGENT_COMPONENT_NAME}.
60+ */
61+ record ModuleEntitlements (
62+ String componentName ,
63+ Map <Class <? extends Entitlement >, List <Entitlement >> entitlementsByType ,
64+ FileAccessTree fileAccess
65+ ) {
5566
5667 ModuleEntitlements {
5768 entitlementsByType = Map .copyOf (entitlementsByType );
5869 }
5970
60- public static ModuleEntitlements from (List <Entitlement > entitlements ) {
71+ public static ModuleEntitlements none (String componentName ) {
72+ return new ModuleEntitlements (componentName , Map .of (), FileAccessTree .EMPTY );
73+ }
74+
75+ public static ModuleEntitlements from (String componentName , List <Entitlement > entitlements ) {
6176 var fileEntitlements = entitlements .stream ()
6277 .filter (e -> e .getClass ().equals (FileEntitlement .class ))
6378 .map (e -> (FileEntitlement ) e )
6479 .toList ();
6580 return new ModuleEntitlements (
81+ componentName ,
6682 entitlements .stream ().collect (groupingBy (Entitlement ::getClass )),
6783 FileAccessTree .of (fileEntitlements )
6884 );
@@ -84,7 +100,7 @@ public <E extends Entitlement> Stream<E> getEntitlements(Class<E> entitlementCla
84100 final Map <Module , ModuleEntitlements > moduleEntitlementsMap = new ConcurrentHashMap <>();
85101
86102 protected final Map <String , List <Entitlement >> serverEntitlements ;
87- protected final List <Entitlement > agentEntitlements ;
103+ protected final List <Entitlement > apmAgentEntitlements ;
88104 protected final Map <String , Map <String , List <Entitlement >>> pluginsEntitlements ;
89105 private final Function <Class <?>, String > pluginResolver ;
90106
@@ -106,9 +122,9 @@ private static Set<Module> findSystemModules() {
106122 }
107123
108124 /**
109- * The package name containing agent classes.
125+ * The package name containing classes from the APM agent .
110126 */
111- private final String agentsPackageName ;
127+ private final String apmAgentPackageName ;
112128
113129 /**
114130 * Frames originating from this module are ignored in the permission logic.
@@ -117,25 +133,25 @@ private static Set<Module> findSystemModules() {
117133
118134 public PolicyManager (
119135 Policy serverPolicy ,
120- List <Entitlement > agentEntitlements ,
136+ List <Entitlement > apmAgentEntitlements ,
121137 Map <String , Policy > pluginPolicies ,
122138 Function <Class <?>, String > pluginResolver ,
123- String agentsPackageName ,
139+ String apmAgentPackageName ,
124140 Module entitlementsModule
125141 ) {
126142 this .serverEntitlements = buildScopeEntitlementsMap (requireNonNull (serverPolicy ));
127- this .agentEntitlements = agentEntitlements ;
143+ this .apmAgentEntitlements = apmAgentEntitlements ;
128144 this .pluginsEntitlements = requireNonNull (pluginPolicies ).entrySet ()
129145 .stream ()
130146 .collect (toUnmodifiableMap (Map .Entry ::getKey , e -> buildScopeEntitlementsMap (e .getValue ())));
131147 this .pluginResolver = pluginResolver ;
132- this .agentsPackageName = agentsPackageName ;
148+ this .apmAgentPackageName = apmAgentPackageName ;
133149 this .entitlementsModule = entitlementsModule ;
134150
135151 for (var e : serverEntitlements .entrySet ()) {
136- validateEntitlementsPerModule ("server" , e .getKey (), e .getValue ());
152+ validateEntitlementsPerModule (SERVER_COMPONENT_NAME , e .getKey (), e .getValue ());
137153 }
138- validateEntitlementsPerModule ("agent" , "unnamed" , agentEntitlements );
154+ validateEntitlementsPerModule (APM_AGENT_COMPONENT_NAME , "unnamed" , apmAgentEntitlements );
139155 for (var p : pluginsEntitlements .entrySet ()) {
140156 for (var m : p .getValue ().entrySet ()) {
141157 validateEntitlementsPerModule (p .getKey (), m .getKey (), m .getValue ());
@@ -147,7 +163,7 @@ private static Map<String, List<Entitlement>> buildScopeEntitlementsMap(Policy p
147163 return policy .scopes ().stream ().collect (toUnmodifiableMap (Scope ::moduleName , Scope ::entitlements ));
148164 }
149165
150- private static void validateEntitlementsPerModule (String sourceName , String moduleName , List <Entitlement > entitlements ) {
166+ private static void validateEntitlementsPerModule (String componentName , String moduleName , List <Entitlement > entitlements ) {
151167 Set <Class <? extends Entitlement >> flagEntitlements = new HashSet <>();
152168 for (var e : entitlements ) {
153169 if (e instanceof FileEntitlement ) {
@@ -156,7 +172,7 @@ private static void validateEntitlementsPerModule(String sourceName, String modu
156172 if (flagEntitlements .contains (e .getClass ())) {
157173 throw new IllegalArgumentException (
158174 "["
159- + sourceName
175+ + componentName
160176 + "] using module ["
161177 + moduleName
162178 + "] found duplicate flag entitlements ["
@@ -184,9 +200,10 @@ private void neverEntitled(Class<?> callerClass, Supplier<String> operationDescr
184200
185201 throw new NotEntitledException (
186202 Strings .format (
187- "Not entitled: caller [%s], module [%s], operation [%s]" ,
188- callerClass ,
189- requestingClass .getModule () == null ? "<none>" : requestingClass .getModule ().getName (),
203+ "Not entitled: component [%s], module [%s], class [%s], operation [%s]" ,
204+ getEntitlements (requestingClass ).componentName (),
205+ requestingClass .getModule ().getName (),
206+ requestingClass ,
190207 operationDescription .get ()
191208 )
192209 );
@@ -240,9 +257,10 @@ public void checkFileRead(Class<?> callerClass, Path path) {
240257 if (entitlements .fileAccess ().canRead (path ) == false ) {
241258 throw new NotEntitledException (
242259 Strings .format (
243- "Not entitled: caller [%s], module [%s], entitlement [file], operation [read], path [%s]" ,
244- callerClass ,
260+ "Not entitled: component [%s], module [%s], class [%s], entitlement [file], operation [read], path [%s]" ,
261+ entitlements . componentName () ,
245262 requestingClass .getModule (),
263+ requestingClass ,
246264 path
247265 )
248266 );
@@ -264,9 +282,10 @@ public void checkFileWrite(Class<?> callerClass, Path path) {
264282 if (entitlements .fileAccess ().canWrite (path ) == false ) {
265283 throw new NotEntitledException (
266284 Strings .format (
267- "Not entitled: caller [%s], module [%s], entitlement [file], operation [write], path [%s]" ,
268- callerClass ,
285+ "Not entitled: component [%s], module [%s], class [%s], entitlement [file], operation [write], path [%s]" ,
286+ entitlements . componentName () ,
269287 requestingClass .getModule (),
288+ requestingClass ,
270289 path
271290 )
272291 );
@@ -300,30 +319,33 @@ public void checkAllNetworkAccess(Class<?> callerClass) {
300319 }
301320
302321 var classEntitlements = getEntitlements (requestingClass );
303- if (classEntitlements .hasEntitlement (InboundNetworkEntitlement .class ) == false ) {
304- throw new NotEntitledException (
305- Strings .format (
306- "Missing entitlement: class [%s], module [%s], entitlement [inbound_network]" ,
307- requestingClass ,
308- requestingClass .getModule ().getName ()
309- )
310- );
311- }
322+ checkFlagEntitlement (classEntitlements , InboundNetworkEntitlement .class , requestingClass );
323+ checkFlagEntitlement (classEntitlements , OutboundNetworkEntitlement .class , requestingClass );
324+ }
312325
313- if (classEntitlements .hasEntitlement (OutboundNetworkEntitlement .class ) == false ) {
326+ private static void checkFlagEntitlement (
327+ ModuleEntitlements classEntitlements ,
328+ Class <? extends Entitlement > entitlementClass ,
329+ Class <?> requestingClass
330+ ) {
331+ if (classEntitlements .hasEntitlement (entitlementClass ) == false ) {
314332 throw new NotEntitledException (
315333 Strings .format (
316- "Missing entitlement: class [%s], module [%s], entitlement [outbound_network]" ,
334+ "Not entitled: component [%s], module [%s], class [%s], entitlement [%s]" ,
335+ classEntitlements .componentName (),
336+ requestingClass .getModule ().getName (),
317337 requestingClass ,
318- requestingClass . getModule (). getName ( )
338+ PolicyParser . getEntitlementTypeName ( entitlementClass )
319339 )
320340 );
321341 }
322342 logger .debug (
323343 () -> Strings .format (
324- "Entitled: class [%s], module [%s], entitlements [inbound_network, outbound_network]" ,
344+ "Entitled: component [%s], module [%s], class [%s], entitlement [%s]" ,
345+ classEntitlements .componentName (),
346+ requestingClass .getModule ().getName (),
325347 requestingClass ,
326- requestingClass . getModule (). getName ( )
348+ PolicyParser . getEntitlementTypeName ( entitlementClass )
327349 )
328350 );
329351 }
@@ -338,19 +360,21 @@ public void checkWriteProperty(Class<?> callerClass, String property) {
338360 if (entitlements .getEntitlements (WriteSystemPropertiesEntitlement .class ).anyMatch (e -> e .properties ().contains (property ))) {
339361 logger .debug (
340362 () -> Strings .format (
341- "Entitled: class [%s], module [%s], entitlement [write_system_properties], property [%s]" ,
342- requestingClass ,
363+ "Entitled: component [%s], module [%s], class [%s], entitlement [write_system_properties], property [%s]" ,
364+ entitlements . componentName () ,
343365 requestingClass .getModule ().getName (),
366+ requestingClass ,
344367 property
345368 )
346369 );
347370 return ;
348371 }
349372 throw new NotEntitledException (
350373 Strings .format (
351- "Missing entitlement: class [%s], module [%s], entitlement [write_system_properties], property [%s]" ,
352- requestingClass ,
374+ "Not entitled: component [%s], module [%s], class [%s], entitlement [write_system_properties], property [%s]" ,
375+ entitlements . componentName () ,
353376 requestingClass .getModule ().getName (),
377+ requestingClass ,
354378 property
355379 )
356380 );
@@ -361,27 +385,7 @@ private void checkEntitlementPresent(Class<?> callerClass, Class<? extends Entit
361385 if (isTriviallyAllowed (requestingClass )) {
362386 return ;
363387 }
364-
365- ModuleEntitlements entitlements = getEntitlements (requestingClass );
366- if (entitlements .hasEntitlement (entitlementClass )) {
367- logger .debug (
368- () -> Strings .format (
369- "Entitled: class [%s], module [%s], entitlement [%s]" ,
370- requestingClass ,
371- requestingClass .getModule ().getName (),
372- PolicyParser .getEntitlementTypeName (entitlementClass )
373- )
374- );
375- return ;
376- }
377- throw new NotEntitledException (
378- Strings .format (
379- "Missing entitlement: class [%s], module [%s], entitlement [%s]" ,
380- requestingClass ,
381- requestingClass .getModule ().getName (),
382- PolicyParser .getEntitlementTypeName (entitlementClass )
383- )
384- );
388+ checkFlagEntitlement (getEntitlements (requestingClass ), entitlementClass , requestingClass );
385389 }
386390
387391 ModuleEntitlements getEntitlements (Class <?> requestingClass ) {
@@ -391,47 +395,44 @@ ModuleEntitlements getEntitlements(Class<?> requestingClass) {
391395 private ModuleEntitlements computeEntitlements (Class <?> requestingClass ) {
392396 Module requestingModule = requestingClass .getModule ();
393397 if (isServerModule (requestingModule )) {
394- return getModuleScopeEntitlements (requestingClass , serverEntitlements , requestingModule .getName (), "server" );
398+ return getModuleScopeEntitlements (serverEntitlements , requestingModule .getName (), SERVER_COMPONENT_NAME );
395399 }
396400
397401 // plugins
398402 var pluginName = pluginResolver .apply (requestingClass );
399403 if (pluginName != null ) {
400404 var pluginEntitlements = pluginsEntitlements .get (pluginName );
401405 if (pluginEntitlements == null ) {
402- return ModuleEntitlements .NONE ;
406+ return ModuleEntitlements .none ( pluginName ) ;
403407 } else {
404408 final String scopeName ;
405409 if (requestingModule .isNamed () == false ) {
406410 scopeName = ALL_UNNAMED ;
407411 } else {
408412 scopeName = requestingModule .getName ();
409413 }
410- return getModuleScopeEntitlements (requestingClass , pluginEntitlements , scopeName , pluginName );
414+ return getModuleScopeEntitlements (pluginEntitlements , scopeName , pluginName );
411415 }
412416 }
413417
414- if (requestingModule .isNamed () == false && requestingClass .getPackageName ().startsWith (agentsPackageName )) {
415- // agents are the only thing running non-modular in the system classloader
416- return ModuleEntitlements .from (agentEntitlements );
418+ if (requestingModule .isNamed () == false && requestingClass .getPackageName ().startsWith (apmAgentPackageName )) {
419+ // The APM agent is the only thing running non-modular in the system classloader
420+ return ModuleEntitlements .from (APM_AGENT_COMPONENT_NAME , apmAgentEntitlements );
417421 }
418422
419- logger .warn ("No applicable entitlement policy for class [{}]" , requestingClass .getName ());
420- return ModuleEntitlements .NONE ;
423+ return ModuleEntitlements .none (UNKNOWN_COMPONENT_NAME );
421424 }
422425
423426 private ModuleEntitlements getModuleScopeEntitlements (
424- Class <?> callerClass ,
425427 Map <String , List <Entitlement >> scopeEntitlements ,
426428 String moduleName ,
427- String component
429+ String componentName
428430 ) {
429431 var entitlements = scopeEntitlements .get (moduleName );
430432 if (entitlements == null ) {
431- logger .warn ("No applicable entitlement policy for [{}], module [{}], class [{}]" , component , moduleName , callerClass );
432- return ModuleEntitlements .NONE ;
433+ return ModuleEntitlements .none (componentName );
433434 }
434- return ModuleEntitlements .from (entitlements );
435+ return ModuleEntitlements .from (componentName , entitlements );
435436 }
436437
437438 private static boolean isServerModule (Module requestingModule ) {
0 commit comments