Skip to content

Commit d8b821c

Browse files
authored
Apply suggestions from code review
Signed-off-by: Nathan Bower <[email protected]>
1 parent 33d963c commit d8b821c

File tree

1 file changed

+17
-17
lines changed

1 file changed

+17
-17
lines changed

_posts/2025-05-19-journey-to-find-replacements-java-security-manager.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ The decision to remove JSM in 3.0 was carefully considered and primarily driven
1818

1919
1. **The upcoming removal of JSM from the Java platform**: JSM has been deprecated since JDK 17 ([JEP411](https://openjdk.org/jeps/411)) and is scheduled for full removal in JDK 24 ([JEP 486](https://openjdk.org/jeps/486)). According to the Java Enhancement Proposal (JEP), this decision was made because very few projects were using JSM, with Elasticsearch being one of the few major open-source projects that did. While OpenSearch 3.0 is bundled with Java 21 and not yet forced to drop JSM, continuing to rely on a deprecated and soon-to-be-removed component was deemed unsustainable for long-term support and innovation.
2020

21-
2. **Incompatibility with emerging JVM features, particularly, virtual threads**: Introduced in ([JEP 444](https://openjdk.org/jeps/444)), virtual threads are one of the most anticipated features in modern Java. While OpenSearch 3.0 does not use virtual threads internally, we expect plugin developers and future versions of OpenSearch to explore using virtual threads for improved scalability. However, virtual threads do not carry permissions when a Security Manager is enabled, effectively rendering them incompatible with any JSM-based security model. Thus, continuing to support JSM would have prevented adoption of a key Java feature that unlocks better concurrency and resource efficiency.
21+
2. **Incompatibility with emerging JVM features, particularly virtual threads**: Introduced in ([JEP 444](https://openjdk.org/jeps/444)), virtual threads are one of the most anticipated features in modern Java. While OpenSearch 3.0 does not use virtual threads internally, we expect plugin developers and future versions of OpenSearch to potentially use virtual threads for improved scalability. However, virtual threads do not carry permissions when a Security Manager is enabled, effectively rendering them incompatible with any JSM-based security model. Thus, continuing to support JSM would have prevented adoption of a key Java feature that unlocks better concurrency and resource efficiency.
2222

2323
Given these needs, we decided to deprecate JSM in OpenSearch 3.0. Doing this in a major version allowed us to communicate the change clearly and avoid introducing breaking security changes in later 3.x minor releases.
2424

2525

26-
In December 2021, an [issue](https://github.com/opensearch-project/OpenSearch/issues/1687) was created in the OpenSearch core repo to discuss options for a replacement. Soon it became clear that there was no direct replacement to the functionality that JSM provided for Java programs. OpenSearch embarked on a lengthy search for a replacement that sought to retain important functionality from JSM that OpenSearch relied on.
26+
In December 2021, an [issue](https://github.com/opensearch-project/OpenSearch/issues/1687) was created in the OpenSearch core repo to discuss options for a replacement. It soon became clear that there was no direct replacement for the functionality that JSM provided for Java programs. OpenSearch embarked on a lengthy search for a replacement that would retain critical JSM functionality.
2727

28-
We considered many different options, including the following notable ones:
28+
We considered many different options, including the following:
2929

3030
1. Moving to [OpenSearch extensibility](https://opensearch.org/blog/technical-roadmap-opensearch-extensibility/) through out-of-process extensions (a radical change).
3131
2. Replacing JVM with GraalVM.
@@ -35,17 +35,17 @@ We considered many different options, including the following notable ones:
3535

3636
## Understanding JSM's role in OpenSearch
3737

38-
At its core, OpenSearch is a powerful search engine built on top of Apache Lucene. It provides a REST API layer for accessing documents stored in Lucene shards, along with built-in cluster management for running Lucene on nodes distributed across a cluster. OpenSearch has a pluggable architecture and a diverse set of plugins that extend the core functionality by offering additional features like security, observability, and index management. OpenSearch plugins run in the same JVM as the OpenSearch process but remain partially separated through separate class loading. OpenSearch does not treat plugins as secure-by-default; instead, it relies on JSM to sandbox plugins in order to prevent them from performing privileged actions without explicit approval by a cluster administrator.
38+
At its core, OpenSearch is a powerful search engine built on top of Apache Lucene. It provides a REST API layer for accessing documents stored in Lucene shards, along with built-in cluster management for running Lucene on nodes distributed across a cluster. OpenSearch has a pluggable architecture and a diverse set of plugins that extend the core functionality by offering additional features like security, observability, and index management. OpenSearch plugins run in the same JVM as the OpenSearch process but remain partially separated through separate class loading. OpenSearch does not treat plugins as secure by default; instead, it relies on JSM to sandbox plugins in order to prevent them from performing privileged actions without explicit cluster administrator approval.
3939

40-
There are two main groups of users that interface with JSM: plugin developers and cluster administrators. These groups use JSM in different ways.
40+
Two main user groups use JSM: plugin developers and cluster administrators. These groups use JSM in different ways.
4141

4242
### How plugin developers use JSM
4343

4444
To perform a privileged action, plugin developers must wrap the code that performs the action in an `AccessController.doPrivileged(() -> { ... })` block and grant the necessary permissions in the `plugin-security.policy` file. A common complaint about JSM is that plugin developers don't know what constitutes a `PrivilegedAction` until runtime. At runtime, they get an error saying that the plugin is forbidden from performing a given operation, for example, connecting to a socket or reading from the file system. JSM enforced a broad range of restrictions, from preventing calls to system operations like `System.exit` to other Java language features like reflection (for more information about the areas that JSM covered, see [Permissions and Security Policy](https://docs.oracle.com/javase/8/docs/technotes/guides/security/spec/security-spec.doc3.html)).
4545

46-
Plugin developers interface with JSM by defining permissions in a policy file and implementing privileged actions in code:
46+
Plugin developers use JSM by defining permissions in a policy file and implementing privileged actions in code:
4747

48-
- The following example `plugin-security.policy` file defines the basic permissions a plugin needs to operate:
48+
- The following example `plugin-security.policy` file defines the basic permissions needed for a plugin to operate:
4949

5050
```json
5151
grant {
@@ -89,16 +89,16 @@ Cluster administrators are prompted about permissions that a plugin requests at
8989

9090
## Our solution for replacing JSM
9191

92-
Understanding the key user interactions with JSM was crucial as we developed our replacement strategy. We needed solutions that would continue to support both plugin developers' need for privileged operations and administrators' ability to control permissions.
92+
Understanding the key JSM user interactions was crucial as we developed our replacement strategy. We needed solutions that would continue to support both plugin developers' need for privileged operations and administrators' ability to control permissions.
9393

94-
After evaluating potential JSM replacement alternatives, it was clear that no single approach could replace all of the functionality that JSM provided. The OpenSearch community came to a consensus to replace JSM by adopting a two-pronged strategy:
94+
After evaluating potential JSM replacement alternatives, it was clear that no single approach could replace all of the functionality that JSM provided. The OpenSearch community decided to replace JSM by adopting a two-pronged strategy:
9595

96-
1. [`systemd` hardening](#systemd-hardening) - Using operating system controls for protection.
97-
2. [Java agent](#java-agent) - Implementing a low-level instrumentation to intercept and authorize privileged operations.
96+
1. [`systemd` hardening](#systemd-hardening): Using operating system controls for protection.
97+
2. [Java agent](#java-agent): Implementing low-level instrumentation to intercept and authorize privileged operations.
9898

9999
### systemd hardening
100100

101-
The first component of the replacement strategy is `systemd` hardening, which is available on Linux distributions that use `systemd` as the init system. This approach sandboxes the OpenSearch process using the following native operating system features:
101+
The first component of the replacement strategy was `systemd` hardening, which is available in Linux distributions that use `systemd` as the init system. This approach sandboxes the OpenSearch process using the following native operating system features:
102102

103103
- **System call restriction**: Uses `seccomp` and the `SystemCallFilter` directive to restrict the kernel interfaces that the OpenSearch process can access.
104104

@@ -108,17 +108,17 @@ The first component of the replacement strategy is `systemd` hardening, which is
108108

109109
- **Process containment**: Enables options such as `PrivateTmp`, `NoNewPrivileges`, and `ProtectSystem` to further reduce the risk of privilege escalation or file system tampering.
110110

111-
This approach is effective for protecting the system from malicious plugins by constraining the actions that the OpenSearch process can perform. However, the drawback is that `systemd` rules are applied at the process level, not at the plugin level. This means that any privilege granted affects the entire OpenSearch process, which is not a suitable replacement for the fine-grained, per-plugin control that JSM provided.
111+
This approach effectively protects the system from malicious plugins by constraining the actions that the OpenSearch process can perform. However, the drawback is that `systemd` rules are applied at the process level, not at the plugin level. This means that any privilege granted affects the entire OpenSearch process, resulting in an unsuitable replacement for the fine-grained, per-plugin control that JSM provided.
112112

113113
### Java agent
114114

115-
The second component of the replacement strategy is a custom Java agent. A Java agent is a special JAR that the JVM can load before application execution or attach during execution in order to view, transform, or monitor the bytecode of every class that the JVM loads. Internally, it relies on the Instrumentation API introduced in Java 5. A Java agent is attached to the OpenSearch process through the `-javaagent` Java argument. The OpenSearch Java agent is composed of interceptors that monitor privileged operations and ensure that the executing codebase has been explicitly granted the required permissions. The configuration for the Java agent remains consistent with the Java Security Manager: the `plugin-security.policy` file defines the set of granted permissions and prompts the cluster administrator during plugin installation.
115+
The second component of the replacement strategy was a custom Java agent. A Java agent is a special JAR that the JVM can load before application execution or attach during execution in order to view, transform, or monitor the bytecode of every class that the JVM loads. Internally, it relies on the Instrumentation API introduced in Java 5. A Java agent is attached to the OpenSearch process through the `-javaagent` Java argument. The OpenSearch Java agent is composed of interceptors that monitor privileged operations and ensure that the executing codebase has been explicitly granted the required permissions. The configuration for the Java agent remains consistent with JSM: the `plugin-security.policy` file defines the set of granted permissions and prompts the cluster administrator during plugin installation.
116116

117-
OpenSearch's Java Agent uses the ByteBuddy Instrumentation API to intercept and instrument Java bytecode at runtime. Specifically, the agent installs interceptors for privileged operations such as:
117+
OpenSearch's Java agent uses the ByteBuddy Instrumentation API to intercept and instrument Java bytecode at runtime. Specifically, the agent installs interceptors for privileged operations such as:
118118

119-
- Opening or connecting sockets
119+
- Opening or connecting sockets.
120120

121-
- Creating, reading, or writing files
121+
- Creating, reading, or writing files.
122122

123123
These interceptors inspect the current call stack to identify the originating code and then evaluate whether it has been granted the required permissions based on the existing `plugin-security.policy` file. This mirrors the existing JSM model, with minimal disruption for plugin developers and administrators.
124124

0 commit comments

Comments
 (0)