|
9 | 9 |
|
10 | 10 | package org.elasticsearch.entitlement.runtime.policy; |
11 | 11 |
|
| 12 | +import org.elasticsearch.entitlement.runtime.api.NotEntitledException; |
| 13 | +import org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement; |
| 14 | +import org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.FileData; |
12 | 15 | import org.elasticsearch.test.ESTestCase; |
| 16 | +import org.hamcrest.text.MatchesPattern; |
13 | 17 |
|
14 | 18 | import java.io.IOException; |
| 19 | +import java.nio.file.Files; |
| 20 | +import java.nio.file.LinkOption; |
| 21 | +import java.nio.file.NoSuchFileException; |
| 22 | +import java.nio.file.Path; |
| 23 | +import java.util.List; |
| 24 | +import java.util.Map; |
15 | 25 | import java.util.Set; |
| 26 | +import java.util.regex.Pattern; |
16 | 27 | import java.util.stream.Stream; |
17 | 28 |
|
| 29 | +import static java.nio.file.LinkOption.NOFOLLOW_LINKS; |
18 | 30 | import static org.elasticsearch.entitlement.runtime.policy.PolicyManagerTests.NO_ENTITLEMENTS_MODULE; |
19 | 31 | import static org.elasticsearch.entitlement.runtime.policy.PolicyManagerTests.TEST_PATH_LOOKUP; |
| 32 | +import static org.elasticsearch.entitlement.runtime.policy.PolicyManagerTests.createEmptyTestServerPolicy; |
20 | 33 | import static org.elasticsearch.entitlement.runtime.policy.PolicyManagerTests.makeClassInItsOwnModule; |
| 34 | +import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode.READ; |
| 35 | +import static org.hamcrest.Matchers.containsString; |
| 36 | +import static org.hamcrest.text.MatchesPattern.matchesPattern; |
21 | 37 |
|
22 | 38 | public class PolicyCheckerImplTests extends ESTestCase { |
23 | 39 | public void testRequestingClassFastPath() throws IOException, ClassNotFoundException { |
@@ -54,8 +70,68 @@ public void testRequestingModuleWithStackWalk() throws IOException, ClassNotFoun |
54 | 70 | ); |
55 | 71 | } |
56 | 72 |
|
| 73 | + /** |
| 74 | + * Set up a situation where the file read entitlement check encounters |
| 75 | + * a strange {@link IOException} that is not {@link NoSuchFileException}. |
| 76 | + * Ensure that the resulting {@link NotEntitledException} makes |
| 77 | + * some effort to indicate the nature of the problem. |
| 78 | + */ |
| 79 | + public void testIOExceptionFollowingSymlink() throws IOException { |
| 80 | + Path dir = createTempDir(); |
| 81 | + Path symlink = dir.resolve("symlink"); |
| 82 | + Path allegedDir = dir.resolve("not_a_dir"); |
| 83 | + Path target = allegedDir.resolve("target"); |
| 84 | + Files.createFile(allegedDir); // Not a dir! |
| 85 | + Files.createSymbolicLink(symlink, target); |
| 86 | + |
| 87 | + PathLookup testPathLookup = new PathLookup() { |
| 88 | + @Override |
| 89 | + public Path pidFile() { |
| 90 | + throw new UnsupportedOperationException(); |
| 91 | + } |
| 92 | + |
| 93 | + @Override |
| 94 | + public Stream<Path> getBaseDirPaths(BaseDir baseDir) { |
| 95 | + return Stream.empty(); |
| 96 | + } |
| 97 | + |
| 98 | + @Override |
| 99 | + public Stream<Path> resolveSettingPaths(BaseDir baseDir, String settingName) { |
| 100 | + throw new UnsupportedOperationException(); |
| 101 | + } |
| 102 | + |
| 103 | + @Override |
| 104 | + public boolean isPathOnDefaultFilesystem(Path path) { |
| 105 | + // We need this to be on the default filesystem or it will be trivially allowed |
| 106 | + return true; |
| 107 | + } |
| 108 | + }; |
| 109 | + |
| 110 | + var policyManager = new TestPolicyManager( |
| 111 | + createEmptyTestServerPolicy(), |
| 112 | + List.of(), |
| 113 | + Map.of("testComponent", new Policy("testPolicy", List.of(new Scope("testModule", List.of(new FilesEntitlement(List.of(FileData.ofPath(symlink, READ)))))))), |
| 114 | + c-> PolicyManager.PolicyScope.plugin("testComponent", "testModule"), |
| 115 | + testPathLookup, |
| 116 | + List.of(), |
| 117 | + List.of() |
| 118 | + ); |
| 119 | + policyManager.setActive(true); |
| 120 | + policyManager.setTriviallyAllowingTestCode(false); |
| 121 | + |
| 122 | + var checker = checker(NO_ENTITLEMENTS_MODULE, policyManager, testPathLookup); |
| 123 | + var exception = assertThrows(NotEntitledException.class, ()->checker.checkFileRead(getClass(), symlink, true)); |
| 124 | + assertThat("The reason should be an exception of some sort", |
| 125 | + exception.getMessage(), matchesPattern(".*reason.*Exception.*")); |
| 126 | + } |
| 127 | + |
57 | 128 | private static PolicyCheckerImpl checker(Module entitlementsModule) { |
58 | | - return new PolicyCheckerImpl(Set.of(), entitlementsModule, null, TEST_PATH_LOOKUP); |
| 129 | + // TODO: TEST_PATH_LOOKUP is always null at this point! |
| 130 | + return checker(entitlementsModule, null, TEST_PATH_LOOKUP); |
| 131 | + } |
| 132 | + |
| 133 | + private static PolicyCheckerImpl checker(Module entitlementsModule, PolicyManager policyManager, PathLookup testPathLookup) { |
| 134 | + return new PolicyCheckerImpl(Set.of(), entitlementsModule, policyManager, testPathLookup); |
59 | 135 | } |
60 | 136 |
|
61 | 137 | } |
0 commit comments