Convert a few entitlements to records (#118705)

* Convert a few entitlements to records

* Make SetHttpsConnectionPropertiesEntitlement a record and fix tests
This commit is contained in:
Patrick Doyle 2025-01-03 12:12:44 -05:00 committed by GitHub
parent 9452a8582b
commit 4eefc6d73b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 23 additions and 85 deletions

View file

@ -128,13 +128,13 @@ public class EntitlementInitialization {
final Policy policy = parsePolicyIfExists(pluginName, policyFile, isExternalPlugin);
// TODO: should this check actually be part of the parser?
for (Scope scope : policy.scopes) {
if (moduleNames.contains(scope.moduleName) == false) {
for (Scope scope : policy.scopes()) {
if (moduleNames.contains(scope.moduleName()) == false) {
throw new IllegalStateException(
Strings.format(
"Invalid module name in policy: plugin [%s] does not have module [%s]; available modules [%s]; policy file [%s]",
pluginName,
scope.moduleName,
scope.moduleName(),
String.join(", ", moduleNames),
policyFile
)

View file

@ -9,7 +9,7 @@
package org.elasticsearch.entitlement.runtime.policy;
public class CreateClassLoaderEntitlement implements Entitlement {
public record CreateClassLoaderEntitlement() implements Entitlement {
@ExternalEntitlement
public CreateClassLoaderEntitlement() {}
public CreateClassLoaderEntitlement {}
}

View file

@ -12,4 +12,4 @@ package org.elasticsearch.entitlement.runtime.policy;
/**
* Internal policy type (not-parseable -- not available to plugins).
*/
public class ExitVMEntitlement implements Entitlement {}
public record ExitVMEntitlement() implements Entitlement {}

View file

@ -9,38 +9,15 @@
package org.elasticsearch.entitlement.runtime.policy;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* A holder for scoped entitlements.
*/
public class Policy {
public final String name;
public final List<Scope> scopes;
public record Policy(String name, List<Scope> scopes) {
public Policy(String name, List<Scope> scopes) {
this.name = Objects.requireNonNull(name);
this.scopes = Collections.unmodifiableList(Objects.requireNonNull(scopes));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Policy policy = (Policy) o;
return Objects.equals(name, policy.name) && Objects.equals(scopes, policy.scopes);
}
@Override
public int hashCode() {
return Objects.hash(name, scopes);
}
@Override
public String toString() {
return "Policy{" + "name='" + name + '\'' + ", scopes=" + scopes + '}';
this.scopes = List.copyOf(scopes);
}
}

View file

@ -99,7 +99,7 @@ public class PolicyManager {
}
private static Map<String, List<Entitlement>> buildScopeEntitlementsMap(Policy policy) {
return policy.scopes.stream().collect(Collectors.toUnmodifiableMap(scope -> scope.moduleName, scope -> scope.entitlements));
return policy.scopes().stream().collect(Collectors.toUnmodifiableMap(scope -> scope.moduleName(), scope -> scope.entitlements()));
}
public void checkStartProcess(Class<?> callerClass) {

View file

@ -9,38 +9,17 @@
package org.elasticsearch.entitlement.runtime.policy;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* A holder for entitlements within a single scope.
*/
public class Scope {
public final String moduleName;
public final List<Entitlement> entitlements;
public record Scope(String moduleName, List<Entitlement> entitlements) {
public Scope(String moduleName, List<Entitlement> entitlements) {
this.moduleName = moduleName;
this.entitlements = Collections.unmodifiableList(Objects.requireNonNull(entitlements));
this.moduleName = Objects.requireNonNull(moduleName);
this.entitlements = List.copyOf(entitlements);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Scope scope = (Scope) o;
return Objects.equals(moduleName, scope.moduleName) && Objects.equals(entitlements, scope.entitlements);
}
@Override
public int hashCode() {
return Objects.hash(moduleName, entitlements);
}
@Override
public String toString() {
return "Scope{" + "name='" + moduleName + '\'' + ", entitlements=" + entitlements + '}';
}
}

View file

@ -12,7 +12,7 @@ package org.elasticsearch.entitlement.runtime.policy;
/**
* An Entitlement to allow setting properties to a single Https connection after this has been created
*/
public class SetHttpsConnectionPropertiesEntitlement implements Entitlement {
public record SetHttpsConnectionPropertiesEntitlement() implements Entitlement {
@ExternalEntitlement(esModulesOnly = false)
public SetHttpsConnectionPropertiesEntitlement() {}
public SetHttpsConnectionPropertiesEntitlement {}
}

View file

@ -16,11 +16,7 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import static org.elasticsearch.test.LambdaMatchers.transformedMatch;
import static org.hamcrest.Matchers.both;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
public class PolicyParserTests extends ESTestCase {
@ -39,21 +35,21 @@ public class PolicyParserTests extends ESTestCase {
public void testPolicyBuilder() throws IOException {
Policy parsedPolicy = new PolicyParser(PolicyParserTests.class.getResourceAsStream("test-policy.yaml"), "test-policy.yaml", false)
.parsePolicy();
Policy builtPolicy = new Policy(
Policy expected = new Policy(
"test-policy.yaml",
List.of(new Scope("entitlement-module-name", List.of(new FileEntitlement("test/path/to/file", List.of("read", "write")))))
);
assertEquals(parsedPolicy, builtPolicy);
assertEquals(expected, parsedPolicy);
}
public void testPolicyBuilderOnExternalPlugin() throws IOException {
Policy parsedPolicy = new PolicyParser(PolicyParserTests.class.getResourceAsStream("test-policy.yaml"), "test-policy.yaml", true)
.parsePolicy();
Policy builtPolicy = new Policy(
Policy expected = new Policy(
"test-policy.yaml",
List.of(new Scope("entitlement-module-name", List.of(new FileEntitlement("test/path/to/file", List.of("read", "write")))))
);
assertEquals(parsedPolicy, builtPolicy);
assertEquals(expected, parsedPolicy);
}
public void testParseCreateClassloader() throws IOException {
@ -61,18 +57,11 @@ public class PolicyParserTests extends ESTestCase {
entitlement-module-name:
- create_class_loader
""".getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", false).parsePolicy();
Policy builtPolicy = new Policy(
Policy expected = new Policy(
"test-policy.yaml",
List.of(new Scope("entitlement-module-name", List.of(new CreateClassLoaderEntitlement())))
);
assertThat(
parsedPolicy.scopes,
contains(
both(transformedMatch((Scope scope) -> scope.moduleName, equalTo("entitlement-module-name"))).and(
transformedMatch(scope -> scope.entitlements, contains(instanceOf(CreateClassLoaderEntitlement.class)))
)
)
);
assertEquals(expected, parsedPolicy);
}
public void testParseSetHttpsConnectionProperties() throws IOException {
@ -80,17 +69,10 @@ public class PolicyParserTests extends ESTestCase {
entitlement-module-name:
- set_https_connection_properties
""".getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", true).parsePolicy();
Policy builtPolicy = new Policy(
Policy expected = new Policy(
"test-policy.yaml",
List.of(new Scope("entitlement-module-name", List.of(new CreateClassLoaderEntitlement())))
);
assertThat(
parsedPolicy.scopes,
contains(
both(transformedMatch((Scope scope) -> scope.moduleName, equalTo("entitlement-module-name"))).and(
transformedMatch(scope -> scope.entitlements, contains(instanceOf(SetHttpsConnectionPropertiesEntitlement.class)))
)
)
List.of(new Scope("entitlement-module-name", List.of(new SetHttpsConnectionPropertiesEntitlement())))
);
assertEquals(expected, parsedPolicy);
}
}