Skip to content

Commit 71f72b9

Browse files
authored
Consolidate path setting files entitlements to config (elastic#123649)
The setting based paths could be either absolute or relative, and they are always relative to the config dir. This commit renames the path_setting to make it clear it is related to config, and removes the relative variant.
1 parent 7f501a5 commit 71f72b9

File tree

4 files changed

+84
-106
lines changed

4 files changed

+84
-106
lines changed

libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java

Lines changed: 33 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,8 @@ static FileData ofRelativePath(Path relativePath, BaseDir baseDir, Mode mode) {
9191
return new RelativePathFileData(relativePath, baseDir, mode, null, false);
9292
}
9393

94-
static FileData ofPathSetting(String setting, Mode mode, boolean ignoreUrl) {
95-
return new PathSettingFileData(setting, mode, ignoreUrl, null, false);
96-
}
97-
98-
static FileData ofRelativePathSetting(String setting, BaseDir baseDir, Mode mode, boolean ignoreUrl) {
99-
return new RelativePathSettingFileData(setting, baseDir, mode, ignoreUrl, null, false);
94+
static FileData ofPathSetting(String setting, BaseDir baseDir, Mode mode, boolean ignoreUrl) {
95+
return new PathSettingFileData(setting, baseDir, mode, ignoreUrl, null, false);
10096
}
10197

10298
/**
@@ -225,71 +221,39 @@ public FileData withPlatform(Platform platform) {
225221
}
226222
}
227223

228-
private record PathSettingFileData(String setting, Mode mode, boolean ignoreUrl, Platform platform, boolean exclusive)
224+
private record PathSettingFileData(String setting, BaseDir baseDir, Mode mode, boolean ignoreUrl, Platform platform, boolean exclusive)
229225
implements
230-
FileData {
226+
RelativeFileData {
231227

232228
@Override
233229
public PathSettingFileData withExclusive(boolean exclusive) {
234-
return new PathSettingFileData(setting, mode, ignoreUrl, platform, exclusive);
235-
}
236-
237-
@Override
238-
public Stream<Path> resolvePaths(PathLookup pathLookup) {
239-
return resolvePathSettings(pathLookup, setting, ignoreUrl);
240-
}
241-
242-
@Override
243-
public FileData withPlatform(Platform platform) {
244-
if (platform == platform()) {
245-
return this;
246-
}
247-
return new PathSettingFileData(setting, mode, ignoreUrl, platform, exclusive);
248-
}
249-
}
250-
251-
private record RelativePathSettingFileData(
252-
String setting,
253-
BaseDir baseDir,
254-
Mode mode,
255-
boolean ignoreUrl,
256-
Platform platform,
257-
boolean exclusive
258-
) implements FileData, RelativeFileData {
259-
260-
@Override
261-
public RelativePathSettingFileData withExclusive(boolean exclusive) {
262-
return new RelativePathSettingFileData(setting, baseDir, mode, ignoreUrl, platform, exclusive);
230+
return new PathSettingFileData(setting, baseDir, mode, ignoreUrl, platform, exclusive);
263231
}
264232

265233
@Override
266234
public Stream<Path> resolveRelativePaths(PathLookup pathLookup) {
267-
return resolvePathSettings(pathLookup, setting, ignoreUrl);
235+
Stream<String> result;
236+
if (setting.contains("*")) {
237+
result = pathLookup.settingGlobResolver().apply(setting);
238+
} else {
239+
String path = pathLookup.settingResolver().apply(setting);
240+
result = path == null ? Stream.of() : Stream.of(path);
241+
}
242+
if (ignoreUrl) {
243+
result = result.filter(s -> s.toLowerCase(Locale.ROOT).startsWith("https://") == false);
244+
}
245+
return result.map(pathLookup.configDir()::resolve);
268246
}
269247

270248
@Override
271249
public FileData withPlatform(Platform platform) {
272250
if (platform == platform()) {
273251
return this;
274252
}
275-
return new RelativePathSettingFileData(setting, baseDir, mode, ignoreUrl, platform, exclusive);
253+
return new PathSettingFileData(setting, baseDir, mode, ignoreUrl, platform, exclusive);
276254
}
277255
}
278256

279-
private static Stream<Path> resolvePathSettings(PathLookup pathLookup, String setting, boolean ignoreUrl) {
280-
Stream<String> result;
281-
if (setting.contains("*")) {
282-
result = pathLookup.settingGlobResolver().apply(setting);
283-
} else {
284-
String path = pathLookup.settingResolver().apply(setting);
285-
result = path == null ? Stream.of() : Stream.of(path);
286-
}
287-
if (ignoreUrl) {
288-
result = result.filter(s -> s.toLowerCase(Locale.ROOT).startsWith("https://") == false);
289-
}
290-
return result.map(Path::of);
291-
}
292-
293257
private static Mode parseMode(String mode) {
294258
if (mode.equals("read")) {
295259
return Mode.READ;
@@ -371,7 +335,7 @@ public static FilesEntitlement build(List<Object> paths) {
371335
String relativePathAsString = checkString.apply(file, "relative_path");
372336
String relativeTo = checkString.apply(file, "relative_to");
373337
String pathSetting = checkString.apply(file, "path_setting");
374-
String relativePathSetting = checkString.apply(file, "relative_path_setting");
338+
String settingBaseDirAsString = checkString.apply(file, "basedir_if_relative");
375339
String modeAsString = checkString.apply(file, "mode");
376340
String platformAsString = checkString.apply(file, "platform");
377341
Boolean ignoreUrlAsStringBoolean = checkBoolean.apply(file, "ignore_url");
@@ -382,11 +346,10 @@ public static FilesEntitlement build(List<Object> paths) {
382346
if (file.isEmpty() == false) {
383347
throw new PolicyValidationException("unknown key(s) [" + file + "] in a listed file for files entitlement");
384348
}
385-
int foundKeys = (pathAsString != null ? 1 : 0) + (relativePathAsString != null ? 1 : 0) + (pathSetting != null ? 1 : 0)
386-
+ (relativePathSetting != null ? 1 : 0);
349+
int foundKeys = (pathAsString != null ? 1 : 0) + (relativePathAsString != null ? 1 : 0) + (pathSetting != null ? 1 : 0);
387350
if (foundKeys != 1) {
388351
throw new PolicyValidationException(
389-
"a files entitlement entry must contain one of " + "[path, relative_path, path_setting, relative_path_setting]"
352+
"a files entitlement entry must contain one of " + "[path, relative_path, path_setting]"
390353
);
391354
}
392355

@@ -399,20 +362,23 @@ public static FilesEntitlement build(List<Object> paths) {
399362
platform = parsePlatform(platformAsString);
400363
}
401364

402-
BaseDir baseDir = null;
403-
if (relativeTo != null) {
404-
baseDir = parseBaseDir(relativeTo);
365+
if (relativeTo != null && relativePathAsString == null) {
366+
throw new PolicyValidationException("'relative_to' may only be used with 'relative_path'");
405367
}
406368

407-
if (ignoreUrlAsStringBoolean != null && (relativePathAsString != null || pathAsString != null)) {
408-
throw new PolicyValidationException("'ignore_url' may only be used with `path_setting` or `relative_path_setting`");
369+
if (ignoreUrlAsStringBoolean != null && pathSetting == null) {
370+
throw new PolicyValidationException("'ignore_url' may only be used with 'path_setting'");
371+
}
372+
if (settingBaseDirAsString != null && pathSetting == null) {
373+
throw new PolicyValidationException("'basedir_if_relative' may only be used with 'path_setting'");
409374
}
410375

411376
final FileData fileData;
412377
if (relativePathAsString != null) {
413-
if (baseDir == null) {
378+
if (relativeTo == null) {
414379
throw new PolicyValidationException("files entitlement with a 'relative_path' must specify 'relative_to'");
415380
}
381+
BaseDir baseDir = parseBaseDir(relativeTo);
416382
Path relativePath = Path.of(relativePathAsString);
417383
if (FileData.isAbsolutePath(relativePathAsString)) {
418384
throw new PolicyValidationException("'relative_path' [" + relativePathAsString + "] must be relative");
@@ -425,12 +391,11 @@ public static FilesEntitlement build(List<Object> paths) {
425391
}
426392
fileData = FileData.ofPath(path, mode);
427393
} else if (pathSetting != null) {
428-
fileData = FileData.ofPathSetting(pathSetting, mode, ignoreUrlAsString);
429-
} else if (relativePathSetting != null) {
430-
if (baseDir == null) {
431-
throw new PolicyValidationException("files entitlement with a 'relative_path_setting' must specify 'relative_to'");
394+
if (settingBaseDirAsString == null) {
395+
throw new PolicyValidationException("files entitlement with a 'path_setting' must specify 'basedir_if_relative'");
432396
}
433-
fileData = FileData.ofRelativePathSetting(relativePathSetting, baseDir, mode, ignoreUrlAsString);
397+
BaseDir baseDir = parseBaseDir(settingBaseDirAsString);
398+
fileData = FileData.ofPathSetting(pathSetting, baseDir, mode, ignoreUrlAsString);
434399
} else {
435400
throw new AssertionError("File entry validation error");
436401
}

libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyParserFailureTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public void testEntitlementMutuallyExclusiveParameters() {
7575
assertEquals(
7676
"[2:5] policy parsing error for [test-failure-policy.yaml] in scope [entitlement-module-name] "
7777
+ "for entitlement type [files]: a files entitlement entry must contain one of "
78-
+ "[path, relative_path, path_setting, relative_path_setting]",
78+
+ "[path, relative_path, path_setting]",
7979
ppe.getMessage()
8080
);
8181
}
@@ -89,7 +89,7 @@ public void testEntitlementAtLeastOneParameter() {
8989
assertEquals(
9090
"[2:5] policy parsing error for [test-failure-policy.yaml] in scope [entitlement-module-name] "
9191
+ "for entitlement type [files]: a files entitlement entry must contain one of "
92-
+ "[path, relative_path, path_setting, relative_path_setting]",
92+
+ "[path, relative_path, path_setting]",
9393
ppe.getMessage()
9494
);
9595
}

libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyParserTests.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,7 @@ public void testParseFiles() throws IOException {
183183
- path: '%s'
184184
mode: "read_write"
185185
- path_setting: foo.bar
186-
mode: read
187-
- relative_path_setting: foo.bar
188-
relative_to: config
186+
basedir_if_relative: config
189187
mode: read
190188
""", relativePathToFile, relativePathToDir, TEST_ABSOLUTE_PATH_TO_FILE).getBytes(StandardCharsets.UTF_8)),
191189
"test-policy.yaml",
@@ -202,8 +200,7 @@ public void testParseFiles() throws IOException {
202200
Map.of("relative_path", relativePathToFile, "mode", "read_write", "relative_to", "data"),
203201
Map.of("relative_path", relativePathToDir, "mode", "read", "relative_to", "config"),
204202
Map.of("path", TEST_ABSOLUTE_PATH_TO_FILE, "mode", "read_write"),
205-
Map.of("path_setting", "foo.bar", "mode", "read"),
206-
Map.of("relative_path_setting", "foo.bar", "relative_to", "config", "mode", "read")
203+
Map.of("path_setting", "foo.bar", "basedir_if_relative", "config", "mode", "read")
207204
)
208205
)
209206
)

libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlementTests.java

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -98,72 +98,88 @@ public void testFileDataRelativeWithEmptyDirectory() {
9898
}
9999

100100
public void testPathSettingResolve() {
101-
var entitlement = FilesEntitlement.build(List.of(Map.of("path_setting", "foo.bar", "mode", "read")));
101+
var entitlement = FilesEntitlement.build(
102+
List.of(Map.of("path_setting", "foo.bar", "basedir_if_relative", "config", "mode", "read"))
103+
);
102104
var filesData = entitlement.filesData();
103-
assertThat(filesData, contains(FileData.ofPathSetting("foo.bar", READ, false)));
105+
assertThat(filesData, contains(FileData.ofPathSetting("foo.bar", CONFIG, READ, false)));
104106

105-
var fileData = FileData.ofPathSetting("foo.bar", READ, false);
107+
var fileData = FileData.ofPathSetting("foo.bar", CONFIG, READ, false);
106108
// empty settings
107109
assertThat(fileData.resolvePaths(TEST_PATH_LOOKUP).toList(), empty());
108110

109-
fileData = FileData.ofPathSetting("foo.bar", READ, false);
111+
fileData = FileData.ofPathSetting("foo.bar", CONFIG, READ, false);
110112
settings = Settings.builder().put("foo.bar", "/setting/path").build();
111113
assertThat(fileData.resolvePaths(TEST_PATH_LOOKUP).toList(), contains(Path.of("/setting/path")));
112114

113-
fileData = FileData.ofPathSetting("foo.*.bar", READ, false);
115+
fileData = FileData.ofPathSetting("foo.*.bar", CONFIG, READ, false);
114116
settings = Settings.builder().put("foo.baz.bar", "/setting/path").build();
115117
assertThat(fileData.resolvePaths(TEST_PATH_LOOKUP).toList(), contains(Path.of("/setting/path")));
116118

117-
fileData = FileData.ofPathSetting("foo.*.bar", READ, false);
119+
fileData = FileData.ofPathSetting("foo.*.bar", CONFIG, READ, false);
118120
settings = Settings.builder().put("foo.baz.bar", "/setting/path").put("foo.baz2.bar", "/other/path").build();
119121
assertThat(fileData.resolvePaths(TEST_PATH_LOOKUP).toList(), containsInAnyOrder(Path.of("/setting/path"), Path.of("/other/path")));
122+
123+
fileData = FileData.ofPathSetting("foo.bar", CONFIG, READ, false);
124+
settings = Settings.builder().put("foo.bar", "relative_path").build();
125+
assertThat(fileData.resolvePaths(TEST_PATH_LOOKUP).toList(), contains(Path.of("/config/relative_path")));
120126
}
121127

122-
public void testExclusiveParsing() throws Exception {
123-
Policy parsedPolicy = new PolicyParser(new ByteArrayInputStream("""
124-
entitlement-module-name:
125-
- files:
126-
- path: /test
127-
mode: read
128-
exclusive: true
129-
""".getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", true).parsePolicy();
130-
Policy expected = new Policy(
131-
"test-policy.yaml",
132-
List.of(
133-
new Scope(
134-
"entitlement-module-name",
135-
List.of(FilesEntitlement.build(List.of(Map.of("path", "/test", "mode", "read", "exclusive", true))))
136-
)
128+
public void testPathSettingBasedirValidation() {
129+
var e = expectThrows(
130+
PolicyValidationException.class,
131+
() -> FilesEntitlement.build(List.of(Map.of("path", "/foo", "mode", "read", "basedir_if_relative", "config")))
132+
);
133+
assertThat(e.getMessage(), is("'basedir_if_relative' may only be used with 'path_setting'"));
134+
135+
e = expectThrows(
136+
PolicyValidationException.class,
137+
() -> FilesEntitlement.build(
138+
List.of(Map.of("relative_path", "foo", "relative_to", "config", "mode", "read", "basedir_if_relative", "config"))
137139
)
138140
);
139-
assertEquals(expected, parsedPolicy);
141+
assertThat(e.getMessage(), is("'basedir_if_relative' may only be used with 'path_setting'"));
140142
}
141143

142144
public void testPathSettingIgnoreUrl() {
143-
var fileData = FileData.ofPathSetting("foo.*.bar", READ, true);
145+
var fileData = FileData.ofPathSetting("foo.*.bar", CONFIG, READ, true);
144146
settings = Settings.builder().put("foo.nonurl.bar", "/setting/path").put("foo.url.bar", "https://mysite").build();
145147
assertThat(fileData.resolvePaths(TEST_PATH_LOOKUP).toList(), contains(Path.of("/setting/path")));
146148
}
147149

148-
public void testRelativePathSettingIgnoreUrl() {
149-
var fileData = FileData.ofRelativePathSetting("foo.*.bar", CONFIG, READ, true);
150-
settings = Settings.builder().put("foo.nonurl.bar", "path").put("foo.url.bar", "https://mysite").build();
151-
assertThat(fileData.resolvePaths(TEST_PATH_LOOKUP).toList(), contains(Path.of("/config/path")));
152-
}
153-
154150
public void testIgnoreUrlValidation() {
155151
var e = expectThrows(
156152
PolicyValidationException.class,
157153
() -> FilesEntitlement.build(List.of(Map.of("path", "/foo", "mode", "read", "ignore_url", true)))
158154
);
159-
assertThat(e.getMessage(), is("'ignore_url' may only be used with `path_setting` or `relative_path_setting`"));
155+
assertThat(e.getMessage(), is("'ignore_url' may only be used with 'path_setting'"));
160156

161157
e = expectThrows(
162158
PolicyValidationException.class,
163159
() -> FilesEntitlement.build(
164160
List.of(Map.of("relative_path", "foo", "relative_to", "config", "mode", "read", "ignore_url", true))
165161
)
166162
);
167-
assertThat(e.getMessage(), is("'ignore_url' may only be used with `path_setting` or `relative_path_setting`"));
163+
assertThat(e.getMessage(), is("'ignore_url' may only be used with 'path_setting'"));
164+
}
165+
166+
public void testExclusiveParsing() throws Exception {
167+
Policy parsedPolicy = new PolicyParser(new ByteArrayInputStream("""
168+
entitlement-module-name:
169+
- files:
170+
- path: /test
171+
mode: read
172+
exclusive: true
173+
""".getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", true).parsePolicy();
174+
Policy expected = new Policy(
175+
"test-policy.yaml",
176+
List.of(
177+
new Scope(
178+
"entitlement-module-name",
179+
List.of(FilesEntitlement.build(List.of(Map.of("path", "/test", "mode", "read", "exclusive", true))))
180+
)
181+
)
182+
);
183+
assertEquals(expected, parsedPolicy);
168184
}
169185
}

0 commit comments

Comments
 (0)