diff --git a/docs/changelog/127877.yaml b/docs/changelog/127877.yaml new file mode 100644 index 000000000000..58f2504e41c3 --- /dev/null +++ b/docs/changelog/127877.yaml @@ -0,0 +1,5 @@ +pr: 127877 +summary: Check hidden frames in entitlements +area: Infra/Core +type: bug +issues: [] diff --git a/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/Util.java b/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/Util.java index 9fd34d3b72c2..a6eb17493fa1 100644 --- a/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/Util.java +++ b/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/Util.java @@ -10,8 +10,10 @@ package org.elasticsearch.entitlement.bridge; import java.util.Optional; +import java.util.Set; import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; +import static java.lang.StackWalker.Option.SHOW_HIDDEN_FRAMES; public class Util { /** @@ -23,6 +25,8 @@ public class Util { public static final Class NO_CLASS = new Object() { }.getClass(); + private static final Set skipInternalPackages = Set.of("java.lang.invoke", "java.lang.reflect", "jdk.internal.reflect"); + /** * Why would we write this instead of using {@link StackWalker#getCallerClass()}? * Because that method throws {@link IllegalCallerException} if called from the "outermost frame", @@ -32,9 +36,10 @@ public class Util { */ @SuppressWarnings("unused") // Called reflectively from InstrumenterImpl public static Class getCallerClass() { - Optional> callerClassIfAny = StackWalker.getInstance(RETAIN_CLASS_REFERENCE) + Optional> callerClassIfAny = StackWalker.getInstance(Set.of(RETAIN_CLASS_REFERENCE, SHOW_HIDDEN_FRAMES)) .walk( frames -> frames.skip(2) // Skip this method and its caller + .filter(frame -> skipInternalPackages.contains(frame.getDeclaringClass().getPackageName()) == false) .findFirst() .map(StackWalker.StackFrame::getDeclaringClass) ); diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java index b15280a9279b..1eab0886bcb5 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java @@ -182,7 +182,9 @@ public record FilesEntitlement(List filesData) implements Entitlement case "config" -> BaseDir.CONFIG; case "data" -> BaseDir.DATA; case "home" -> BaseDir.USER_HOME; - // NOTE: shared_repo is _not_ accessible to policy files, only internally + // it would be nice to limit this to just ES modules, but we don't have a way to plumb that through to here + // however, we still don't document in the error case below that shared_repo is valid + case "shared_repo" -> BaseDir.SHARED_REPO; default -> throw new PolicyValidationException( "invalid relative directory: " + baseDir + ", valid values: [config, data, home]" ); diff --git a/modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml b/modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml index 081ac21f8886..2a8ea227e701 100644 --- a/modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml +++ b/modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,2 +1,8 @@ +org.elasticsearch.repository.url: + - outbound_network + - files: + - relative_path: . + relative_to: shared_repo + mode: read org.apache.httpcomponents.httpclient: - outbound_network # for URLHttpClient