Skip to content

Commit ef154a6

Browse files
Refactor: ScopeResolver (#126921) (#127174) (#127183)
* Fix: use getScopeName consistently * Rename PolicyManagerTests method * Refacor: simplify PluginsResolver.create * Change PluginsResolver to ScopeResolver * Move boot layer test to ScopeResolverTests * [CI] Auto commit changes from spotless * Rename PolicyScope * Add ComponentKind enum * Package private componentName field --------- Co-authored-by: elasticsearchmachine <infra-root+elasticsearchmachine@elastic.co>
1 parent 3cc8807 commit ef154a6

File tree

8 files changed

+260
-233
lines changed

8 files changed

+260
-233
lines changed

libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/EntitlementBootstrap.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.elasticsearch.entitlement.runtime.policy.PathLookup;
2222
import org.elasticsearch.entitlement.runtime.policy.PathLookupImpl;
2323
import org.elasticsearch.entitlement.runtime.policy.Policy;
24+
import org.elasticsearch.entitlement.runtime.policy.PolicyManager;
2425
import org.elasticsearch.logging.LogManager;
2526
import org.elasticsearch.logging.Logger;
2627

@@ -39,14 +40,14 @@ public class EntitlementBootstrap {
3940
public record BootstrapArgs(
4041
@Nullable Policy serverPolicyPatch,
4142
Map<String, Policy> pluginPolicies,
42-
Function<Class<?>, String> pluginResolver,
43+
Function<Class<?>, PolicyManager.PolicyScope> scopeResolver,
4344
PathLookup pathLookup,
4445
Map<String, Path> sourcePaths,
4546
Set<Class<?>> suppressFailureLogClasses
4647
) {
4748
public BootstrapArgs {
4849
requireNonNull(pluginPolicies);
49-
requireNonNull(pluginResolver);
50+
requireNonNull(scopeResolver);
5051
requireNonNull(pathLookup);
5152
requireNonNull(sourcePaths);
5253
requireNonNull(suppressFailureLogClasses);
@@ -65,7 +66,7 @@ public static BootstrapArgs bootstrapArgs() {
6566
*
6667
* @param serverPolicyPatch a policy with additional entitlements to patch the embedded server layer policy
6768
* @param pluginPolicies a map holding policies for plugins (and modules), by plugin (or module) name.
68-
* @param pluginResolver a functor to map a Java Class to the plugin it belongs to (the plugin name).
69+
* @param scopeResolver a functor to map a Java Class to the component and module it belongs to.
6970
* @param settingResolver a functor to resolve a setting name pattern for one or more Elasticsearch settings.
7071
* @param dataDirs data directories for Elasticsearch
7172
* @param sharedRepoDirs shared repository directories for Elasticsearch
@@ -82,7 +83,7 @@ public static BootstrapArgs bootstrapArgs() {
8283
public static void bootstrap(
8384
Policy serverPolicyPatch,
8485
Map<String, Policy> pluginPolicies,
85-
Function<Class<?>, String> pluginResolver,
86+
Function<Class<?>, PolicyManager.PolicyScope> scopeResolver,
8687
Function<String, Stream<String>> settingResolver,
8788
Path[] dataDirs,
8889
Path[] sharedRepoDirs,
@@ -103,7 +104,7 @@ public static void bootstrap(
103104
EntitlementBootstrap.bootstrapArgs = new BootstrapArgs(
104105
serverPolicyPatch,
105106
pluginPolicies,
106-
pluginResolver,
107+
scopeResolver,
107108
new PathLookupImpl(
108109
getUserHome(),
109110
configDir,

libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@
9090
*/
9191
public class EntitlementInitialization {
9292

93-
private static final String AGENTS_PACKAGE_NAME = "co.elastic.apm.agent";
9493
private static final Module ENTITLEMENTS_MODULE = PolicyManager.class.getModule();
9594

9695
private static ElasticsearchEntitlementChecker manager;
@@ -350,9 +349,8 @@ private static PolicyManager createPolicyManager() {
350349
serverPolicy,
351350
agentEntitlements,
352351
pluginPolicies,
353-
EntitlementBootstrap.bootstrapArgs().pluginResolver(),
352+
EntitlementBootstrap.bootstrapArgs().scopeResolver(),
354353
EntitlementBootstrap.bootstrapArgs().sourcePaths(),
355-
AGENTS_PACKAGE_NAME,
356354
ENTITLEMENTS_MODULE,
357355
pathLookup,
358356
bootstrapArgs.suppressFailureLogClasses()

libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java

+84-59
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@
5959
import static java.util.zip.ZipFile.OPEN_READ;
6060
import static org.elasticsearch.entitlement.bridge.Util.NO_CLASS;
6161
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;
6266

6367
/**
6468
* 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 {
128132
*/
129133
private static final Logger generalLogger = LogManager.getLogger(PolicyManager.class);
130134

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-
135135
static final Class<?> DEFAULT_FILESYSTEM_CLASS = PathUtils.getDefaultFileSystem().getClass();
136136

137137
static final Set<String> MODULES_EXCLUDED_FROM_SYSTEM_MODULES = Set.of("java.desktop");
138138

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+
139184
/**
140185
* This class contains all the entitlements by type, plus the {@link FileAccessTree} for the special case of filesystem entitlements.
141186
* <p>
@@ -209,7 +254,7 @@ ModuleEntitlements policyEntitlements(String componentName, Path componentPath,
209254
private final Map<String, List<Entitlement>> serverEntitlements;
210255
private final List<Entitlement> apmAgentEntitlements;
211256
private final Map<String, Map<String, List<Entitlement>>> pluginsEntitlements;
212-
private final Function<Class<?>, String> pluginResolver;
257+
private final Function<Class<?>, PolicyScope> scopeResolver;
213258
private final PathLookup pathLookup;
214259
private final Set<Class<?>> mutedClasses;
215260

@@ -245,10 +290,6 @@ private static Set<Module> findSystemLayerModules() {
245290
.collect(Collectors.toUnmodifiableSet());
246291

247292
private final Map<String, Path> sourcePaths;
248-
/**
249-
* The package name containing classes from the APM agent.
250-
*/
251-
private final String apmAgentPackageName;
252293

253294
/**
254295
* Frames originating from this module are ignored in the permission logic.
@@ -266,9 +307,8 @@ public PolicyManager(
266307
Policy serverPolicy,
267308
List<Entitlement> apmAgentEntitlements,
268309
Map<String, Policy> pluginPolicies,
269-
Function<Class<?>, String> pluginResolver,
310+
Function<Class<?>, PolicyScope> scopeResolver,
270311
Map<String, Path> sourcePaths,
271-
String apmAgentPackageName,
272312
Module entitlementsModule,
273313
PathLookup pathLookup,
274314
Set<Class<?>> suppressFailureLogClasses
@@ -278,18 +318,17 @@ public PolicyManager(
278318
this.pluginsEntitlements = requireNonNull(pluginPolicies).entrySet()
279319
.stream()
280320
.collect(toUnmodifiableMap(Map.Entry::getKey, e -> buildScopeEntitlementsMap(e.getValue())));
281-
this.pluginResolver = pluginResolver;
321+
this.scopeResolver = scopeResolver;
282322
this.sourcePaths = sourcePaths;
283-
this.apmAgentPackageName = apmAgentPackageName;
284323
this.entitlementsModule = entitlementsModule;
285324
this.pathLookup = requireNonNull(pathLookup);
286325
this.mutedClasses = suppressFailureLogClasses;
287326

288327
List<ExclusiveFileEntitlement> exclusiveFileEntitlements = new ArrayList<>();
289328
for (var e : serverEntitlements.entrySet()) {
290-
validateEntitlementsPerModule(SERVER_COMPONENT_NAME, e.getKey(), e.getValue(), exclusiveFileEntitlements);
329+
validateEntitlementsPerModule(SERVER.componentName, e.getKey(), e.getValue(), exclusiveFileEntitlements);
291330
}
292-
validateEntitlementsPerModule(APM_AGENT_COMPONENT_NAME, ALL_UNNAMED, apmAgentEntitlements, exclusiveFileEntitlements);
331+
validateEntitlementsPerModule(APM_AGENT.componentName, ALL_UNNAMED, apmAgentEntitlements, exclusiveFileEntitlements);
293332
for (var p : pluginsEntitlements.entrySet()) {
294333
for (var m : p.getValue().entrySet()) {
295334
validateEntitlementsPerModule(p.getKey(), m.getKey(), m.getValue(), exclusiveFileEntitlements);
@@ -684,50 +723,40 @@ ModuleEntitlements getEntitlements(Class<?> requestingClass) {
684723
}
685724

686725
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();
696729

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 -> {
704732
return getModuleScopeEntitlements(
705-
pluginEntitlements,
706-
getScopeName(requestingModule),
707-
pluginName,
708-
sourcePaths.get(pluginName)
733+
serverEntitlements,
734+
moduleName,
735+
SERVER.componentName,
736+
getComponentPathFromClass(requestingClass)
709737
);
710738
}
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+
}
731760
}
732761
}
733762

@@ -763,10 +792,6 @@ private ModuleEntitlements getModuleScopeEntitlements(
763792
return policyEntitlements(componentName, componentPath, scopeName, entitlements);
764793
}
765794

766-
private static boolean isServerModule(Module requestingModule) {
767-
return requestingModule.isNamed() && requestingModule.getLayer() == ModuleLayer.boot();
768-
}
769-
770795
/**
771796
* Walks the stack to determine which class should be checked for entitlements.
772797
*

0 commit comments

Comments
 (0)