Skip to content

Commit 15c2c46

Browse files
prdoyleelasticsearchmachine
andauthored
Refactor: ScopeResolver (#126921)
* 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 <[email protected]>
1 parent 4efa176 commit 15c2c46

File tree

8 files changed

+258
-235
lines changed

8 files changed

+258
-235
lines changed

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

Lines changed: 6 additions & 5 deletions
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

Lines changed: 1 addition & 3 deletions
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;
@@ -314,9 +313,8 @@ private static PolicyManager createPolicyManager() {
314313
serverPolicy,
315314
agentEntitlements,
316315
pluginPolicies,
317-
EntitlementBootstrap.bootstrapArgs().pluginResolver(),
316+
EntitlementBootstrap.bootstrapArgs().scopeResolver(),
318317
EntitlementBootstrap.bootstrapArgs().sourcePaths(),
319-
AGENTS_PACKAGE_NAME,
320318
ENTITLEMENTS_MODULE,
321319
pathLookup,
322320
bootstrapArgs.suppressFailureLogClasses()

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

Lines changed: 82 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,66 @@
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
public class PolicyManager {
6468
/**
6569
* Use this if you don't have a {@link ModuleEntitlements} in hand.
6670
*/
6771
private static final Logger generalLogger = LogManager.getLogger(PolicyManager.class);
6872

69-
static final String UNKNOWN_COMPONENT_NAME = "(unknown)";
70-
static final String SERVER_COMPONENT_NAME = "(server)";
71-
static final String APM_AGENT_COMPONENT_NAME = "(APM agent)";
72-
7373
static final Class<?> DEFAULT_FILESYSTEM_CLASS = PathUtils.getDefaultFileSystem().getClass();
7474

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

7777
/**
78-
* @param componentName the plugin name; or else one of the special component names
79-
* like {@link #SERVER_COMPONENT_NAME} or {@link #APM_AGENT_COMPONENT_NAME}.
78+
* Identifies a particular entitlement {@link Scope} within a {@link Policy}.
8079
*/
80+
public record PolicyScope(ComponentKind kind, String componentName, String moduleName) {
81+
public PolicyScope {
82+
requireNonNull(kind);
83+
requireNonNull(componentName);
84+
requireNonNull(moduleName);
85+
assert kind.componentName == null || kind.componentName.equals(componentName);
86+
}
87+
88+
public static PolicyScope unknown(String moduleName) {
89+
return new PolicyScope(UNKNOWN, UNKNOWN.componentName, moduleName);
90+
}
91+
92+
public static PolicyScope server(String moduleName) {
93+
return new PolicyScope(SERVER, SERVER.componentName, moduleName);
94+
}
95+
96+
public static PolicyScope apmAgent(String moduleName) {
97+
return new PolicyScope(APM_AGENT, APM_AGENT.componentName, moduleName);
98+
}
99+
100+
public static PolicyScope plugin(String componentName, String moduleName) {
101+
return new PolicyScope(PLUGIN, componentName, moduleName);
102+
}
103+
}
104+
105+
public enum ComponentKind {
106+
UNKNOWN("(unknown)"),
107+
SERVER("(server)"),
108+
APM_AGENT("(APM agent)"),
109+
PLUGIN(null);
110+
111+
/**
112+
* If this kind corresponds to a single component, this is that component's name;
113+
* otherwise null.
114+
*/
115+
final String componentName;
116+
117+
ComponentKind(String componentName) {
118+
this.componentName = componentName;
119+
}
120+
}
121+
81122
record ModuleEntitlements(
82123
String componentName,
83124
Map<Class<? extends Entitlement>, List<Entitlement>> entitlementsByType,
@@ -132,7 +173,7 @@ ModuleEntitlements policyEntitlements(String componentName, Path componentPath,
132173
private final Map<String, List<Entitlement>> serverEntitlements;
133174
private final List<Entitlement> apmAgentEntitlements;
134175
private final Map<String, Map<String, List<Entitlement>>> pluginsEntitlements;
135-
private final Function<Class<?>, String> pluginResolver;
176+
private final Function<Class<?>, PolicyScope> scopeResolver;
136177
private final PathLookup pathLookup;
137178
private final Set<Class<?>> mutedClasses;
138179

@@ -168,10 +209,6 @@ private static Set<Module> findSystemLayerModules() {
168209
.collect(Collectors.toUnmodifiableSet());
169210

170211
private final Map<String, Path> sourcePaths;
171-
/**
172-
* The package name containing classes from the APM agent.
173-
*/
174-
private final String apmAgentPackageName;
175212

176213
/**
177214
* Frames originating from this module are ignored in the permission logic.
@@ -189,9 +226,8 @@ public PolicyManager(
189226
Policy serverPolicy,
190227
List<Entitlement> apmAgentEntitlements,
191228
Map<String, Policy> pluginPolicies,
192-
Function<Class<?>, String> pluginResolver,
229+
Function<Class<?>, PolicyScope> scopeResolver,
193230
Map<String, Path> sourcePaths,
194-
String apmAgentPackageName,
195231
Module entitlementsModule,
196232
PathLookup pathLookup,
197233
Set<Class<?>> suppressFailureLogClasses
@@ -201,18 +237,17 @@ public PolicyManager(
201237
this.pluginsEntitlements = requireNonNull(pluginPolicies).entrySet()
202238
.stream()
203239
.collect(toUnmodifiableMap(Map.Entry::getKey, e -> buildScopeEntitlementsMap(e.getValue())));
204-
this.pluginResolver = pluginResolver;
240+
this.scopeResolver = scopeResolver;
205241
this.sourcePaths = sourcePaths;
206-
this.apmAgentPackageName = apmAgentPackageName;
207242
this.entitlementsModule = entitlementsModule;
208243
this.pathLookup = requireNonNull(pathLookup);
209244
this.mutedClasses = suppressFailureLogClasses;
210245

211246
List<ExclusiveFileEntitlement> exclusiveFileEntitlements = new ArrayList<>();
212247
for (var e : serverEntitlements.entrySet()) {
213-
validateEntitlementsPerModule(SERVER_COMPONENT_NAME, e.getKey(), e.getValue(), exclusiveFileEntitlements);
248+
validateEntitlementsPerModule(SERVER.componentName, e.getKey(), e.getValue(), exclusiveFileEntitlements);
214249
}
215-
validateEntitlementsPerModule(APM_AGENT_COMPONENT_NAME, ALL_UNNAMED, apmAgentEntitlements, exclusiveFileEntitlements);
250+
validateEntitlementsPerModule(APM_AGENT.componentName, ALL_UNNAMED, apmAgentEntitlements, exclusiveFileEntitlements);
216251
for (var p : pluginsEntitlements.entrySet()) {
217252
for (var m : p.getValue().entrySet()) {
218253
validateEntitlementsPerModule(p.getKey(), m.getKey(), m.getValue(), exclusiveFileEntitlements);
@@ -607,50 +642,40 @@ ModuleEntitlements getEntitlements(Class<?> requestingClass) {
607642
}
608643

609644
private ModuleEntitlements computeEntitlements(Class<?> requestingClass) {
610-
Module requestingModule = requestingClass.getModule();
611-
if (isServerModule(requestingModule)) {
612-
return getModuleScopeEntitlements(
613-
serverEntitlements,
614-
requestingModule.getName(),
615-
SERVER_COMPONENT_NAME,
616-
getComponentPathFromClass(requestingClass)
617-
);
618-
}
645+
var policyScope = scopeResolver.apply(requestingClass);
646+
var componentName = policyScope.componentName();
647+
var moduleName = policyScope.moduleName();
619648

620-
// plugins
621-
var pluginName = pluginResolver.apply(requestingClass);
622-
if (pluginName != null) {
623-
var pluginEntitlements = pluginsEntitlements.get(pluginName);
624-
if (pluginEntitlements == null) {
625-
return defaultEntitlements(pluginName, sourcePaths.get(pluginName), requestingModule.getName());
626-
} else {
649+
switch (policyScope.kind()) {
650+
case SERVER -> {
627651
return getModuleScopeEntitlements(
628-
pluginEntitlements,
629-
getScopeName(requestingModule),
630-
pluginName,
631-
sourcePaths.get(pluginName)
652+
serverEntitlements,
653+
moduleName,
654+
SERVER.componentName,
655+
getComponentPathFromClass(requestingClass)
632656
);
633657
}
634-
}
635-
636-
if (requestingModule.isNamed() == false && requestingClass.getPackageName().startsWith(apmAgentPackageName)) {
637-
// The APM agent is the only thing running non-modular in the system classloader
638-
return policyEntitlements(
639-
APM_AGENT_COMPONENT_NAME,
640-
getComponentPathFromClass(requestingClass),
641-
ALL_UNNAMED,
642-
apmAgentEntitlements
643-
);
644-
}
645-
646-
return defaultEntitlements(UNKNOWN_COMPONENT_NAME, null, requestingModule.getName());
647-
}
648-
649-
private static String getScopeName(Module requestingModule) {
650-
if (requestingModule.isNamed() == false) {
651-
return ALL_UNNAMED;
652-
} else {
653-
return requestingModule.getName();
658+
case APM_AGENT -> {
659+
// The APM agent is the only thing running non-modular in the system classloader
660+
return policyEntitlements(
661+
APM_AGENT.componentName,
662+
getComponentPathFromClass(requestingClass),
663+
ALL_UNNAMED,
664+
apmAgentEntitlements
665+
);
666+
}
667+
case UNKNOWN -> {
668+
return defaultEntitlements(UNKNOWN.componentName, null, moduleName);
669+
}
670+
default -> {
671+
assert policyScope.kind() == PLUGIN;
672+
var pluginEntitlements = pluginsEntitlements.get(componentName);
673+
if (pluginEntitlements == null) {
674+
return defaultEntitlements(componentName, sourcePaths.get(componentName), moduleName);
675+
} else {
676+
return getModuleScopeEntitlements(pluginEntitlements, moduleName, componentName, sourcePaths.get(componentName));
677+
}
678+
}
654679
}
655680
}
656681

@@ -686,10 +711,6 @@ private ModuleEntitlements getModuleScopeEntitlements(
686711
return policyEntitlements(componentName, componentPath, scopeName, entitlements);
687712
}
688713

689-
private static boolean isServerModule(Module requestingModule) {
690-
return requestingModule.isNamed() && requestingModule.getLayer() == ModuleLayer.boot();
691-
}
692-
693714
/**
694715
* Walks the stack to determine which class should be checked for entitlements.
695716
*

0 commit comments

Comments
 (0)