Skip to content

Commit 1af3ce5

Browse files
committed
Move FilesEntitlements validation to a separate class
1 parent f1f7459 commit 1af3ce5

File tree

3 files changed

+104
-77
lines changed

3 files changed

+104
-77
lines changed

libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java

Lines changed: 1 addition & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
import org.elasticsearch.core.Booleans;
1313
import org.elasticsearch.core.PathUtils;
14-
import org.elasticsearch.core.Strings;
1514
import org.elasticsearch.core.internal.provider.ProviderLocator;
1615
import org.elasticsearch.entitlement.bootstrap.EntitlementBootstrap;
1716
import org.elasticsearch.entitlement.bridge.EntitlementChecker;
@@ -21,7 +20,6 @@
2120
import org.elasticsearch.entitlement.instrumentation.MethodKey;
2221
import org.elasticsearch.entitlement.instrumentation.Transformer;
2322
import org.elasticsearch.entitlement.runtime.api.ElasticsearchEntitlementChecker;
24-
import org.elasticsearch.entitlement.runtime.policy.FileAccessTree;
2523
import org.elasticsearch.entitlement.runtime.policy.PathLookup;
2624
import org.elasticsearch.entitlement.runtime.policy.Policy;
2725
import org.elasticsearch.entitlement.runtime.policy.PolicyManager;
@@ -60,7 +58,6 @@
6058
import java.util.ArrayList;
6159
import java.util.Collections;
6260
import java.util.HashMap;
63-
import java.util.HashSet;
6461
import java.util.List;
6562
import java.util.Map;
6663
import java.util.Set;
@@ -345,7 +342,7 @@ private static PolicyManager createPolicyManager() {
345342
)
346343
);
347344

348-
validateFilesEntitlements(pluginPolicies, pathLookup);
345+
FilesEntitlementsValidation.validate(pluginPolicies, pathLookup);
349346

350347
return new PolicyManager(
351348
serverPolicy,
@@ -359,74 +356,6 @@ private static PolicyManager createPolicyManager() {
359356
);
360357
}
361358

362-
// package visible for tests
363-
static void validateFilesEntitlements(Map<String, Policy> pluginPolicies, PathLookup pathLookup) {
364-
Set<Path> readAccessForbidden = new HashSet<>();
365-
pathLookup.getBaseDirPaths(PLUGINS).forEach(p -> readAccessForbidden.add(p.toAbsolutePath().normalize()));
366-
pathLookup.getBaseDirPaths(MODULES).forEach(p -> readAccessForbidden.add(p.toAbsolutePath().normalize()));
367-
pathLookup.getBaseDirPaths(LIB).forEach(p -> readAccessForbidden.add(p.toAbsolutePath().normalize()));
368-
Set<Path> writeAccessForbidden = new HashSet<>();
369-
pathLookup.getBaseDirPaths(CONFIG).forEach(p -> writeAccessForbidden.add(p.toAbsolutePath().normalize()));
370-
for (var pluginPolicy : pluginPolicies.entrySet()) {
371-
for (var scope : pluginPolicy.getValue().scopes()) {
372-
var filesEntitlement = scope.entitlements()
373-
.stream()
374-
.filter(x -> x instanceof FilesEntitlement)
375-
.map(x -> ((FilesEntitlement) x))
376-
.findFirst();
377-
if (filesEntitlement.isPresent()) {
378-
var fileAccessTree = FileAccessTree.withoutExclusivePaths(filesEntitlement.get(), pathLookup, null);
379-
validateReadFilesEntitlements(pluginPolicy.getKey(), scope.moduleName(), fileAccessTree, readAccessForbidden);
380-
validateWriteFilesEntitlements(pluginPolicy.getKey(), scope.moduleName(), fileAccessTree, writeAccessForbidden);
381-
}
382-
}
383-
}
384-
}
385-
386-
private static IllegalArgumentException buildValidationException(
387-
String componentName,
388-
String moduleName,
389-
Path forbiddenPath,
390-
FilesEntitlement.Mode mode
391-
) {
392-
return new IllegalArgumentException(
393-
Strings.format(
394-
"policy for module [%s] in [%s] has an invalid file entitlement. Any path under [%s] is forbidden for mode [%s].",
395-
moduleName,
396-
componentName,
397-
forbiddenPath,
398-
mode
399-
)
400-
);
401-
}
402-
403-
private static void validateReadFilesEntitlements(
404-
String componentName,
405-
String moduleName,
406-
FileAccessTree fileAccessTree,
407-
Set<Path> readForbiddenPaths
408-
) {
409-
410-
for (Path forbiddenPath : readForbiddenPaths) {
411-
if (fileAccessTree.canRead(forbiddenPath)) {
412-
throw buildValidationException(componentName, moduleName, forbiddenPath, READ);
413-
}
414-
}
415-
}
416-
417-
private static void validateWriteFilesEntitlements(
418-
String componentName,
419-
String moduleName,
420-
FileAccessTree fileAccessTree,
421-
Set<Path> writeForbiddenPaths
422-
) {
423-
for (Path forbiddenPath : writeForbiddenPaths) {
424-
if (fileAccessTree.canWrite(forbiddenPath)) {
425-
throw buildValidationException(componentName, moduleName, forbiddenPath, READ_WRITE);
426-
}
427-
}
428-
}
429-
430359
private static Path getUserHome() {
431360
String userHome = System.getProperty("user.home");
432361
if (userHome == null) {
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.entitlement.initialization;
11+
12+
import org.elasticsearch.core.Strings;
13+
import org.elasticsearch.entitlement.runtime.policy.FileAccessTree;
14+
import org.elasticsearch.entitlement.runtime.policy.PathLookup;
15+
import org.elasticsearch.entitlement.runtime.policy.Policy;
16+
import org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement;
17+
18+
import java.nio.file.Path;
19+
import java.util.HashSet;
20+
import java.util.Map;
21+
import java.util.Set;
22+
23+
import static org.elasticsearch.entitlement.runtime.policy.PathLookup.BaseDir.CONFIG;
24+
import static org.elasticsearch.entitlement.runtime.policy.PathLookup.BaseDir.LIB;
25+
import static org.elasticsearch.entitlement.runtime.policy.PathLookup.BaseDir.MODULES;
26+
import static org.elasticsearch.entitlement.runtime.policy.PathLookup.BaseDir.PLUGINS;
27+
import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode.READ;
28+
import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode.READ_WRITE;
29+
30+
class FilesEntitlementsValidation {
31+
32+
static void validate(Map<String, Policy> pluginPolicies, PathLookup pathLookup) {
33+
Set<Path> readAccessForbidden = new HashSet<>();
34+
pathLookup.getBaseDirPaths(PLUGINS).forEach(p -> readAccessForbidden.add(p.toAbsolutePath().normalize()));
35+
pathLookup.getBaseDirPaths(MODULES).forEach(p -> readAccessForbidden.add(p.toAbsolutePath().normalize()));
36+
pathLookup.getBaseDirPaths(LIB).forEach(p -> readAccessForbidden.add(p.toAbsolutePath().normalize()));
37+
Set<Path> writeAccessForbidden = new HashSet<>();
38+
pathLookup.getBaseDirPaths(CONFIG).forEach(p -> writeAccessForbidden.add(p.toAbsolutePath().normalize()));
39+
for (var pluginPolicy : pluginPolicies.entrySet()) {
40+
for (var scope : pluginPolicy.getValue().scopes()) {
41+
var filesEntitlement = scope.entitlements()
42+
.stream()
43+
.filter(x -> x instanceof FilesEntitlement)
44+
.map(x -> ((FilesEntitlement) x))
45+
.findFirst();
46+
if (filesEntitlement.isPresent()) {
47+
var fileAccessTree = FileAccessTree.withoutExclusivePaths(filesEntitlement.get(), pathLookup, null);
48+
validateReadFilesEntitlements(pluginPolicy.getKey(), scope.moduleName(), fileAccessTree, readAccessForbidden);
49+
validateWriteFilesEntitlements(pluginPolicy.getKey(), scope.moduleName(), fileAccessTree, writeAccessForbidden);
50+
}
51+
}
52+
}
53+
}
54+
55+
private static IllegalArgumentException buildValidationException(
56+
String componentName,
57+
String moduleName,
58+
Path forbiddenPath,
59+
FilesEntitlement.Mode mode
60+
) {
61+
return new IllegalArgumentException(
62+
Strings.format(
63+
"policy for module [%s] in [%s] has an invalid file entitlement. Any path under [%s] is forbidden for mode [%s].",
64+
moduleName,
65+
componentName,
66+
forbiddenPath,
67+
mode
68+
)
69+
);
70+
}
71+
72+
private static void validateReadFilesEntitlements(
73+
String componentName,
74+
String moduleName,
75+
FileAccessTree fileAccessTree,
76+
Set<Path> readForbiddenPaths
77+
) {
78+
79+
for (Path forbiddenPath : readForbiddenPaths) {
80+
if (fileAccessTree.canRead(forbiddenPath)) {
81+
throw buildValidationException(componentName, moduleName, forbiddenPath, READ);
82+
}
83+
}
84+
}
85+
86+
private static void validateWriteFilesEntitlements(
87+
String componentName,
88+
String moduleName,
89+
FileAccessTree fileAccessTree,
90+
Set<Path> writeForbiddenPaths
91+
) {
92+
for (Path forbiddenPath : writeForbiddenPaths) {
93+
if (fileAccessTree.canWrite(forbiddenPath)) {
94+
throw buildValidationException(componentName, moduleName, forbiddenPath, READ_WRITE);
95+
}
96+
}
97+
}
98+
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import static org.hamcrest.Matchers.endsWith;
2828
import static org.hamcrest.Matchers.startsWith;
2929

30-
public class EntitlementInitializationTests extends ESTestCase {
30+
public class FilesEntitlementsValidationTests extends ESTestCase {
3131

3232
private static PathLookup TEST_PATH_LOOKUP;
3333

@@ -75,7 +75,7 @@ public void testValidationPass() {
7575
)
7676
)
7777
);
78-
EntitlementInitialization.validateFilesEntitlements(Map.of("plugin", policy), TEST_PATH_LOOKUP);
78+
FilesEntitlementsValidation.validate(Map.of("plugin", policy), TEST_PATH_LOOKUP);
7979
}
8080

8181
public void testValidationFailForRead() {
@@ -94,7 +94,7 @@ public void testValidationFailForRead() {
9494

9595
var ex = expectThrows(
9696
IllegalArgumentException.class,
97-
() -> EntitlementInitialization.validateFilesEntitlements(Map.of("plugin", policy), TEST_PATH_LOOKUP)
97+
() -> FilesEntitlementsValidation.validate(Map.of("plugin", policy), TEST_PATH_LOOKUP)
9898
);
9999
assertThat(
100100
ex.getMessage(),
@@ -119,7 +119,7 @@ public void testValidationFailForRead() {
119119

120120
ex = expectThrows(
121121
IllegalArgumentException.class,
122-
() -> EntitlementInitialization.validateFilesEntitlements(Map.of("plugin2", policy2), TEST_PATH_LOOKUP)
122+
() -> FilesEntitlementsValidation.validate(Map.of("plugin2", policy2), TEST_PATH_LOOKUP)
123123
);
124124
assertThat(
125125
ex.getMessage(),
@@ -145,7 +145,7 @@ public void testValidationFailForWrite() {
145145

146146
var ex = expectThrows(
147147
IllegalArgumentException.class,
148-
() -> EntitlementInitialization.validateFilesEntitlements(Map.of("plugin", policy), TEST_PATH_LOOKUP)
148+
() -> FilesEntitlementsValidation.validate(Map.of("plugin", policy), TEST_PATH_LOOKUP)
149149
);
150150
assertThat(
151151
ex.getMessage(),

0 commit comments

Comments
 (0)