Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libs/entitlement/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

exports org.elasticsearch.entitlement.runtime.api;
exports org.elasticsearch.entitlement.runtime.policy;
exports org.elasticsearch.entitlement.runtime.policy.entitlements to org.elasticsearch.server;
exports org.elasticsearch.entitlement.instrumentation;
exports org.elasticsearch.entitlement.bootstrap to org.elasticsearch.server;
exports org.elasticsearch.entitlement.initialization to java.base;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
import org.elasticsearch.entitlement.instrumentation.MethodKey;
import org.elasticsearch.entitlement.instrumentation.Transformer;
import org.elasticsearch.entitlement.runtime.api.ElasticsearchEntitlementChecker;
import org.elasticsearch.entitlement.runtime.policy.CreateClassLoaderEntitlement;
import org.elasticsearch.entitlement.runtime.policy.Entitlement;
import org.elasticsearch.entitlement.runtime.policy.ExitVMEntitlement;
import org.elasticsearch.entitlement.runtime.policy.InboundNetworkEntitlement;
import org.elasticsearch.entitlement.runtime.policy.LoadNativeLibrariesEntitlement;
import org.elasticsearch.entitlement.runtime.policy.OutboundNetworkEntitlement;
import org.elasticsearch.entitlement.runtime.policy.Policy;
import org.elasticsearch.entitlement.runtime.policy.PolicyManager;
import org.elasticsearch.entitlement.runtime.policy.Scope;
import org.elasticsearch.entitlement.runtime.policy.entitlements.CreateClassLoaderEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.Entitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.ExitVMEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.InboundNetworkEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.LoadNativeLibrariesEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.OutboundNetworkEntitlement;

import java.lang.instrument.Instrumentation;
import java.lang.reflect.Constructor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

package org.elasticsearch.entitlement.runtime.policy;

import org.elasticsearch.entitlement.runtime.policy.entitlements.Entitlement;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
package org.elasticsearch.entitlement.runtime.policy;

import org.elasticsearch.core.SuppressForbidden;
import org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement;

import java.io.File;
import java.nio.file.Path;
Expand All @@ -18,13 +19,13 @@
import java.util.List;
import java.util.Objects;

final class FileAccessTree {
static final FileAccessTree EMPTY = new FileAccessTree(List.of());
public final class FileAccessTree {
public static final FileAccessTree EMPTY = new FileAccessTree(List.of());

private final String[] readPaths;
private final String[] writePaths;

FileAccessTree(List<FileEntitlement> fileEntitlements) {
private FileAccessTree(List<FileEntitlement> fileEntitlements) {
List<String> readPaths = new ArrayList<>();
List<String> writePaths = new ArrayList<>();
for (FileEntitlement fileEntitlement : fileEntitlements) {
Expand All @@ -42,6 +43,10 @@ final class FileAccessTree {
this.writePaths = writePaths.toArray(new String[0]);
}

public static FileAccessTree of(List<FileEntitlement> fileEntitlements) {
return new FileAccessTree(fileEntitlements);
}

boolean canRead(Path path) {
return checkPath(normalize(path), readPaths);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@
import org.elasticsearch.core.SuppressForbidden;
import org.elasticsearch.entitlement.instrumentation.InstrumentationService;
import org.elasticsearch.entitlement.runtime.api.NotEntitledException;
import org.elasticsearch.entitlement.runtime.policy.entitlements.CreateClassLoaderEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.Entitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.ExitVMEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.InboundNetworkEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.LoadNativeLibrariesEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.OutboundNetworkEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.SetHttpsConnectionPropertiesEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.WriteSystemPropertiesEntitlement;
import org.elasticsearch.logging.LogManager;
import org.elasticsearch.logging.Logger;

Expand All @@ -21,6 +30,7 @@
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand Down Expand Up @@ -54,7 +64,7 @@ public static ModuleEntitlements from(List<Entitlement> entitlements) {
.toList();
return new ModuleEntitlements(
entitlements.stream().collect(groupingBy(Entitlement::getClass)),
new FileAccessTree(fileEntitlements)
FileAccessTree.of(fileEntitlements)
);
}

Expand Down Expand Up @@ -121,12 +131,43 @@ public PolicyManager(
this.pluginResolver = pluginResolver;
this.agentsPackageName = agentsPackageName;
this.entitlementsModule = entitlementsModule;

for (var e : serverEntitlements.entrySet()) {
validateEntitlementsPerModule("server", e.getKey(), e.getValue());
}
validateEntitlementsPerModule("agent", "unnamed", agentEntitlements);
for (var p : pluginsEntitlements.entrySet()) {
for (var m : p.getValue().entrySet()) {
validateEntitlementsPerModule(p.getKey(), m.getKey(), m.getValue());
}
}
}

private static Map<String, List<Entitlement>> buildScopeEntitlementsMap(Policy policy) {
return policy.scopes().stream().collect(toUnmodifiableMap(Scope::moduleName, Scope::entitlements));
}

private static void validateEntitlementsPerModule(String sourceName, String moduleName, List<Entitlement> entitlements) {
Set<Class<? extends Entitlement>> flagEntitlements = new HashSet<>();
for (var e : entitlements) {
if (e instanceof FileEntitlement) {
continue;
}
if (flagEntitlements.contains(e.getClass())) {
throw new IllegalArgumentException(
"["
+ sourceName
+ "] using module ["
+ moduleName
+ "] found duplicate flag entitlements ["
+ e.getClass().getName()
+ "]"
);
}
flagEntitlements.add(e.getClass());
}
}

public void checkStartProcess(Class<?> callerClass) {
neverEntitled(callerClass, "start process");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@

package org.elasticsearch.entitlement.runtime.policy;

import org.elasticsearch.entitlement.runtime.policy.entitlements.CreateClassLoaderEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.Entitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.InboundNetworkEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.LoadNativeLibrariesEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.OutboundNetworkEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.SetHttpsConnectionPropertiesEntitlement;
import org.elasticsearch.entitlement.runtime.policy.entitlements.WriteSystemPropertiesEntitlement;
import org.elasticsearch.xcontent.XContentLocation;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
* parser is able to wrap this exception with a line/character number for
* additional useful error information.
*/
class PolicyValidationException extends RuntimeException {
public class PolicyValidationException extends RuntimeException {

PolicyValidationException(String message) {
public PolicyValidationException(String message) {
super(message);
}

PolicyValidationException(String message, Throwable cause) {
public PolicyValidationException(String message, Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

package org.elasticsearch.entitlement.runtime.policy;

import org.elasticsearch.entitlement.runtime.policy.entitlements.Entitlement;

import java.util.List;
import java.util.Objects;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.entitlement.runtime.policy;
package org.elasticsearch.entitlement.runtime.policy.entitlements;

import org.elasticsearch.entitlement.runtime.policy.ExternalEntitlement;

public record CreateClassLoaderEntitlement() implements Entitlement {
@ExternalEntitlement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.entitlement.runtime.policy;
package org.elasticsearch.entitlement.runtime.policy.entitlements;

import org.elasticsearch.entitlement.runtime.policy.Policy;

/**
* Marker interface to ensure that only {@link Entitlement} are
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.entitlement.runtime.policy;
package org.elasticsearch.entitlement.runtime.policy.entitlements;

/**
* Internal policy type (not-parseable -- not available to plugins).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.entitlement.runtime.policy;
package org.elasticsearch.entitlement.runtime.policy.entitlements;

import org.elasticsearch.entitlement.runtime.policy.ExternalEntitlement;
import org.elasticsearch.entitlement.runtime.policy.PolicyValidationException;

import java.nio.file.Paths;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.entitlement.runtime.policy;
package org.elasticsearch.entitlement.runtime.policy.entitlements;

import org.elasticsearch.entitlement.runtime.policy.ExternalEntitlement;

/**
* Describes an entitlement for inbound network actions (listen/accept/receive)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.entitlement.runtime.policy;
package org.elasticsearch.entitlement.runtime.policy.entitlements;

import org.elasticsearch.entitlement.runtime.policy.ExternalEntitlement;

/**
* An Entitlement to allow loading native libraries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.entitlement.runtime.policy;
package org.elasticsearch.entitlement.runtime.policy.entitlements;

import org.elasticsearch.entitlement.runtime.policy.ExternalEntitlement;

/**
* Describes an entitlement for outbound network actions (connect/send)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.entitlement.runtime.policy;
package org.elasticsearch.entitlement.runtime.policy.entitlements;

import org.elasticsearch.entitlement.runtime.policy.ExternalEntitlement;

/**
* An Entitlement to allow setting properties to a single Https connection after this has been created
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.entitlement.runtime.policy;
package org.elasticsearch.entitlement.runtime.policy.entitlements;

import org.elasticsearch.entitlement.runtime.policy.ExternalEntitlement;

/**
* An Entitlement to allow writing all properties such as system properties.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.entitlement.runtime.policy;
package org.elasticsearch.entitlement.runtime.policy.entitlements;

import org.elasticsearch.entitlement.runtime.policy.ExternalEntitlement;

import java.util.List;
import java.util.Set;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

package org.elasticsearch.entitlement.runtime.policy;

import org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement;
import org.elasticsearch.test.ESTestCase;
import org.junit.BeforeClass;

Expand All @@ -31,13 +32,13 @@ private static Path path(String s) {
}

public void testEmpty() {
var tree = new FileAccessTree(List.of());
var tree = FileAccessTree.of(List.of());
assertThat(tree.canRead(path("path")), is(false));
assertThat(tree.canWrite(path("path")), is(false));
}

public void testRead() {
var tree = new FileAccessTree(List.of(entitlement("foo", "read")));
var tree = FileAccessTree.of(List.of(entitlement("foo", "read")));
assertThat(tree.canRead(path("foo")), is(true));
assertThat(tree.canRead(path("foo/subdir")), is(true));
assertThat(tree.canWrite(path("foo")), is(false));
Expand All @@ -47,7 +48,7 @@ public void testRead() {
}

public void testWrite() {
var tree = new FileAccessTree(List.of(entitlement("foo", "read_write")));
var tree = FileAccessTree.of(List.of(entitlement("foo", "read_write")));
assertThat(tree.canWrite(path("foo")), is(true));
assertThat(tree.canWrite(path("foo/subdir")), is(true));
assertThat(tree.canRead(path("foo")), is(true));
Expand All @@ -57,7 +58,7 @@ public void testWrite() {
}

public void testTwoPaths() {
var tree = new FileAccessTree(List.of(entitlement("foo", "read"), entitlement("bar", "read")));
var tree = FileAccessTree.of(List.of(entitlement("foo", "read"), entitlement("bar", "read")));
assertThat(tree.canRead(path("a")), is(false));
assertThat(tree.canRead(path("bar")), is(true));
assertThat(tree.canRead(path("bar/subdir")), is(true));
Expand All @@ -68,15 +69,15 @@ public void testTwoPaths() {
}

public void testReadWriteUnderRead() {
var tree = new FileAccessTree(List.of(entitlement("foo", "read"), entitlement("foo/bar", "read_write")));
var tree = FileAccessTree.of(List.of(entitlement("foo", "read"), entitlement("foo/bar", "read_write")));
assertThat(tree.canRead(path("foo")), is(true));
assertThat(tree.canWrite(path("foo")), is(false));
assertThat(tree.canRead(path("foo/bar")), is(true));
assertThat(tree.canWrite(path("foo/bar")), is(true));
}

public void testNormalizePath() {
var tree = new FileAccessTree(List.of(entitlement("foo/../bar", "read")));
var tree = FileAccessTree.of(List.of(entitlement("foo/../bar", "read")));
assertThat(tree.canRead(path("foo/../bar")), is(true));
assertThat(tree.canRead(path("foo")), is(false));
assertThat(tree.canRead(path("")), is(false));
Expand Down
Loading