Log NotEntitledExceptions using logger with <package> suffix (#131031)

Log NotEntitledExceptions using logger with `<component>.<module>.<package>` suffix (instead of `<component>.<module>`) for more fine-grained mutes, but remaining backwards compatible regarding existing mutes.

Relates to ES-12231
This commit is contained in:
Moritz Mack 2025-07-15 13:21:54 +02:00 committed by GitHub
parent bfb3aee8ea
commit 92ab85d26d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 39 additions and 59 deletions

View File

@ -137,7 +137,7 @@ public class PolicyCheckerImpl implements PolicyChecker {
requestingClass,
operationDescription.get()
),
callerClass,
requestingClass,
entitlements
);
}
@ -249,7 +249,7 @@ public class PolicyCheckerImpl implements PolicyChecker {
requestingClass,
realPath == null ? path : Strings.format("%s -> %s", path, realPath)
),
callerClass,
requestingClass,
entitlements
);
}
@ -281,7 +281,7 @@ public class PolicyCheckerImpl implements PolicyChecker {
requestingClass,
path
),
callerClass,
requestingClass,
entitlements
);
}
@ -358,8 +358,8 @@ public class PolicyCheckerImpl implements PolicyChecker {
}
var classEntitlements = policyManager.getEntitlements(requestingClass);
checkFlagEntitlement(classEntitlements, InboundNetworkEntitlement.class, requestingClass, callerClass);
checkFlagEntitlement(classEntitlements, OutboundNetworkEntitlement.class, requestingClass, callerClass);
checkFlagEntitlement(classEntitlements, InboundNetworkEntitlement.class, requestingClass);
checkFlagEntitlement(classEntitlements, OutboundNetworkEntitlement.class, requestingClass);
}
@Override
@ -376,16 +376,15 @@ public class PolicyCheckerImpl implements PolicyChecker {
ModuleEntitlements entitlements = policyManager.getEntitlements(requestingClass);
if (entitlements.getEntitlements(WriteSystemPropertiesEntitlement.class).anyMatch(e -> e.properties().contains(property))) {
entitlements.logger()
.debug(
() -> Strings.format(
"Entitled: component [%s], module [%s], class [%s], entitlement [write_system_properties], property [%s]",
entitlements.componentName(),
entitlements.moduleName(),
requestingClass,
property
)
);
PolicyManager.generalLogger.debug(
() -> Strings.format(
"Entitled: component [%s], module [%s], class [%s], entitlement [write_system_properties], property [%s]",
entitlements.componentName(),
entitlements.moduleName(),
requestingClass,
property
)
);
return;
}
notEntitled(
@ -396,7 +395,7 @@ public class PolicyCheckerImpl implements PolicyChecker {
requestingClass,
property
),
callerClass,
requestingClass,
entitlements
);
}
@ -437,8 +436,7 @@ public class PolicyCheckerImpl implements PolicyChecker {
private void checkFlagEntitlement(
ModuleEntitlements classEntitlements,
Class<? extends Entitlement> entitlementClass,
Class<?> requestingClass,
Class<?> callerClass
Class<?> requestingClass
) {
if (classEntitlements.hasEntitlement(entitlementClass) == false) {
notEntitled(
@ -449,27 +447,26 @@ public class PolicyCheckerImpl implements PolicyChecker {
requestingClass,
PolicyParser.buildEntitlementNameFromClass(entitlementClass)
),
callerClass,
requestingClass,
classEntitlements
);
}
classEntitlements.logger()
.debug(
() -> Strings.format(
"Entitled: component [%s], module [%s], class [%s], entitlement [%s]",
classEntitlements.componentName(),
classEntitlements.moduleName(),
requestingClass,
PolicyParser.buildEntitlementNameFromClass(entitlementClass)
)
);
PolicyManager.generalLogger.debug(
() -> Strings.format(
"Entitled: component [%s], module [%s], class [%s], entitlement [%s]",
classEntitlements.componentName(),
classEntitlements.moduleName(),
requestingClass,
PolicyParser.buildEntitlementNameFromClass(entitlementClass)
)
);
}
private void notEntitled(String message, Class<?> callerClass, ModuleEntitlements entitlements) {
private void notEntitled(String message, Class<?> requestingClass, ModuleEntitlements entitlements) {
var exception = new NotEntitledException(message);
// Don't emit a log for suppressed packages, e.g. packages containing self tests
if (suppressFailureLogPackages.contains(callerClass.getPackage()) == false) {
entitlements.logger().warn("Not entitled: {}", message, exception);
if (suppressFailureLogPackages.contains(requestingClass.getPackage()) == false) {
entitlements.logger(requestingClass).warn("Not entitled: {}", message, exception);
}
throw exception;
}
@ -480,7 +477,7 @@ public class PolicyCheckerImpl implements PolicyChecker {
if (policyManager.isTriviallyAllowed(requestingClass)) {
return;
}
checkFlagEntitlement(policyManager.getEntitlements(requestingClass), entitlementClass, requestingClass, callerClass);
checkFlagEntitlement(policyManager.getEntitlements(requestingClass), entitlementClass, requestingClass);
}
@Override

View File

@ -124,8 +124,7 @@ public class PolicyManager {
String componentName,
String moduleName,
Map<Class<? extends Entitlement>, List<Entitlement>> entitlementsByType,
FileAccessTree fileAccess,
Logger logger
FileAccessTree fileAccess
) {
public ModuleEntitlements {
@ -143,6 +142,12 @@ public class PolicyManager {
}
return entitlements.stream().map(entitlementClass::cast);
}
Logger logger(Class<?> requestingClass) {
var packageName = requestingClass.getPackageName();
var loggerSuffix = "." + componentName + "." + ((moduleName == null) ? ALL_UNNAMED : moduleName) + "." + packageName;
return LogManager.getLogger(PolicyManager.class.getName() + loggerSuffix);
}
}
private FileAccessTree getDefaultFileAccess(Collection<Path> componentPaths) {
@ -151,13 +156,7 @@ public class PolicyManager {
// pkg private for testing
ModuleEntitlements defaultEntitlements(String componentName, Collection<Path> componentPaths, String moduleName) {
return new ModuleEntitlements(
componentName,
moduleName,
Map.of(),
getDefaultFileAccess(componentPaths),
getLogger(componentName, moduleName)
);
return new ModuleEntitlements(componentName, moduleName, Map.of(), getDefaultFileAccess(componentPaths));
}
// pkg private for testing
@ -177,8 +176,7 @@ public class PolicyManager {
componentName,
moduleName,
entitlements.stream().collect(groupingBy(Entitlement::getClass)),
FileAccessTree.of(componentName, moduleName, filesEntitlement, pathLookup, componentPaths, exclusivePaths),
getLogger(componentName, moduleName)
FileAccessTree.of(componentName, moduleName, filesEntitlement, pathLookup, componentPaths, exclusivePaths)
);
}
@ -288,21 +286,6 @@ public class PolicyManager {
}
}
private static Logger getLogger(String componentName, String moduleName) {
var loggerSuffix = "." + componentName + "." + ((moduleName == null) ? ALL_UNNAMED : moduleName);
return MODULE_LOGGERS.computeIfAbsent(PolicyManager.class.getName() + loggerSuffix, LogManager::getLogger);
}
/**
* We want to use the same {@link Logger} object for a given name, because we want {@link ModuleEntitlements}
* {@code equals} and {@code hashCode} to work.
* <p>
* This would not be required if LogManager
* <a href="https://github.com/elastic/elasticsearch/issues/87511">memoized the loggers</a>,
* but here we are.
*/
private static final ConcurrentHashMap<String, Logger> MODULE_LOGGERS = new ConcurrentHashMap<>();
protected ModuleEntitlements getEntitlements(Class<?> requestingClass) {
return moduleEntitlementsMap.computeIfAbsent(requestingClass.getModule(), m -> computeEntitlements(requestingClass));
}