Stable analysis plugin with native library fails entitlements in Elasticsearch 8.19.12

Stable analysis plugin with native library fails entitlements in Elasticsearch 8.19.12

We are building a stable-analysis plugin that registers a custom TokenFilter via the stable plugin API. The plugin needs to load a bundled native library.

The plugin works in Gradle-managed yamlRestTest, but in Docker Elasticsearch 8.19.12 it fails on the first _analyze call with a native-loading entitlement error.

Environment

  • Elasticsearch Docker image: docker.elastic.co/elasticsearch/elasticsearch:8.19.12
  • Plugin type: stable-analysis plugin
  • Component type: custom TokenFilter
  • Native library: bundled inside the plugin resources and loaded at runtime
  • Plugin ZIP installs successfully
  • Plugin appears in _cat/plugins / _nodes/plugins
  • Node starts successfully before the first _analyze request

Runtime failure

On the first _analyze request, the node exits with:

Not entitled: component [acme-analysis],
module [synthetic.acme.analysis],
class [class com.acme.EmbeddedLibraryTools],
entitlement [load_native_libraries]

The relevant class is the one that ultimately calls System.load(...) for the extracted native library.

Entitlement policy tried: ALL-UNNAMED

We added the following file:

src/main/plugin-metadata/entitlement-policy.yaml

with this content:

ALL-UNNAMED:
  - load_native_libraries

The policy is packaged at the root of the plugin ZIP and is installed correctly.

We verified all three copies:

  • source file
  • ZIP contents
  • installed plugin directory under /usr/share/elasticsearch/plugins/acme-analysis/

All contain exactly:

ALL-UNNAMED:
  - load_native_libraries

Docker logs also show that Elasticsearch sees the entitlement request:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@     WARNING: plugin requires additional entitlements    @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* load_native_libraries

The JVM arguments also include:

--enable-native-access=ALL-UNNAMED

Despite that, the first _analyze request still fails with:

Not entitled: component [acme-analysis], module [synthetic.acme.analysis], class [class com.acme.EmbeddedLibraryTools], entitlement [load_native_libraries]

So ALL-UNNAMED is accepted and appears to enable native access for ALL-UNNAMED, but the runtime entitlement check attributes the call to synthetic.acme.analysis instead.

Entitlement policy tried: synthetic.acme.analysis

We then tried targeting the runtime-reported module directly:

synthetic.acme.analysis:
  - load_native_libraries

That fails during Elasticsearch boot with:

Invalid module name in policy: layer [acme-analysis] does not have module [synthetic.acme.analysis]; available modules [ALL-UNNAMED]; policy path [/usr/share/elasticsearch/plugins/acme-analysis/entitlement-policy.yaml]

So the policy validator says the plugin layer only exposes:

ALL-UNNAMED

but the runtime entitlement failure reports:

synthetic.acme.analysis

Helper module experiment

We also tried moving the actual System.load(...) call into a separate helper JAR included in the stable plugin ZIP.

The helper JAR is an explicit Java module:

acme.nativebridge

It contains:

com.acme.nativebridge.NativeLibraryLoader

and the actual native-loading call is now inside that helper class:

System.load(...)

The helper JAR is packaged at the root of the plugin ZIP:

nativebridge-0.0.1.jar

jar --describe-module reports it as an explicit module:

acme.nativebridge

We then used this entitlement policy:

acme.nativebridge:
  - load_native_libraries

But Elasticsearch 8.19.12 rejects it at boot:

Invalid module name in policy: layer [acme-analysis] does not have module [acme.nativebridge]; available modules [ALL-UNNAMED]; policy path [/usr/share/elasticsearch/plugins/acme-analysis/entitlement-policy.yaml]

So even an explicit helper module packaged inside the stable-analysis plugin ZIP does not appear to be visible to the entitlement policy validator. The validator still reports only:

ALL-UNNAMED

Summary of what we have confirmed

  1. The plugin ZIP is mounted and installed correctly.
  2. entitlement-policy.yaml is packaged and installed correctly.
  3. ALL-UNNAMED is accepted by Elasticsearch.
  4. Elasticsearch logs show load_native_libraries as a required entitlement.
  5. Elasticsearch JVM args include --enable-native-access=ALL-UNNAMED.
  6. The node starts and the plugin is visible before _analyze.
  7. The first _analyze request still fails because the native load is attributed to synthetic.acme.analysis.
  8. Targeting synthetic.acme.analysis directly is rejected by the policy validator.
  9. A separately packaged explicit helper module is also rejected by the policy validator; the validator still reports only ALL-UNNAMED.
  10. The same plugin works in Gradle-managed yamlRestTest, but not in real Docker Elasticsearch 8.19.12.

Question

Can stable-analysis plugins in Elasticsearch 8.19.x load native libraries under the entitlement system?

If yes, what should the entitlement-policy.yaml scope be for a stable-analysis plugin whose runtime entitlement failure reports:

module [synthetic.acme.analysis]

when the policy validator only accepts:

ALL-UNNAMED

If no, is native library loading under the new entitlement system only supported for classic plugins in 8.19.x?

More generally: how should a stable-analysis plugin that needs load_native_libraries be packaged and scoped in entitlement-policy.yaml?