1010package org .elasticsearch .entitlement .initialization ;
1111
1212import org .elasticsearch .core .Booleans ;
13- import org .elasticsearch .core .Strings ;
1413import org .elasticsearch .entitlement .bootstrap .EntitlementBootstrap ;
1514import org .elasticsearch .entitlement .bridge .EntitlementChecker ;
1615import org .elasticsearch .entitlement .runtime .api .ElasticsearchEntitlementChecker ;
17- import org .elasticsearch .entitlement .runtime .policy .FileAccessTree ;
1816import org .elasticsearch .entitlement .runtime .policy .PathLookup ;
1917import org .elasticsearch .entitlement .runtime .policy .Policy ;
2018import org .elasticsearch .entitlement .runtime .policy .PolicyManager ;
21- import org .elasticsearch .entitlement .runtime .policy .PolicyUtils ;
22- import org .elasticsearch .entitlement .runtime .policy .Scope ;
23- import org .elasticsearch .entitlement .runtime .policy .entitlements .CreateClassLoaderEntitlement ;
24- import org .elasticsearch .entitlement .runtime .policy .entitlements .Entitlement ;
25- import org .elasticsearch .entitlement .runtime .policy .entitlements .ExitVMEntitlement ;
26- import org .elasticsearch .entitlement .runtime .policy .entitlements .FilesEntitlement ;
27- import org .elasticsearch .entitlement .runtime .policy .entitlements .FilesEntitlement .FileData ;
28- import org .elasticsearch .entitlement .runtime .policy .entitlements .InboundNetworkEntitlement ;
29- import org .elasticsearch .entitlement .runtime .policy .entitlements .LoadNativeLibrariesEntitlement ;
30- import org .elasticsearch .entitlement .runtime .policy .entitlements .ManageThreadsEntitlement ;
31- import org .elasticsearch .entitlement .runtime .policy .entitlements .OutboundNetworkEntitlement ;
32- import org .elasticsearch .entitlement .runtime .policy .entitlements .ReadStoreAttributesEntitlement ;
33- import org .elasticsearch .entitlement .runtime .policy .entitlements .SetHttpsConnectionPropertiesEntitlement ;
34- import org .elasticsearch .entitlement .runtime .policy .entitlements .WriteSystemPropertiesEntitlement ;
3519
3620import java .lang .instrument .Instrumentation ;
3721import java .lang .reflect .Constructor ;
3822import java .lang .reflect .InvocationTargetException ;
39- import java .nio .file .Path ;
40- import java .util .ArrayList ;
41- import java .util .Collections ;
42- import java .util .HashSet ;
43- import java .util .List ;
4423import java .util .Map ;
4524import java .util .Set ;
4625
47- import static org .elasticsearch .entitlement .runtime .policy .PathLookup .BaseDir .CONFIG ;
48- import static org .elasticsearch .entitlement .runtime .policy .PathLookup .BaseDir .DATA ;
49- import static org .elasticsearch .entitlement .runtime .policy .PathLookup .BaseDir .LIB ;
50- import static org .elasticsearch .entitlement .runtime .policy .PathLookup .BaseDir .LOGS ;
51- import static org .elasticsearch .entitlement .runtime .policy .PathLookup .BaseDir .MODULES ;
52- import static org .elasticsearch .entitlement .runtime .policy .PathLookup .BaseDir .PLUGINS ;
53- import static org .elasticsearch .entitlement .runtime .policy .PathLookup .BaseDir .SHARED_REPO ;
54- import static org .elasticsearch .entitlement .runtime .policy .Platform .LINUX ;
55- import static org .elasticsearch .entitlement .runtime .policy .entitlements .FilesEntitlement .Mode .READ ;
56- import static org .elasticsearch .entitlement .runtime .policy .entitlements .FilesEntitlement .Mode .READ_WRITE ;
57-
5826/**
5927 * Called by the agent during {@code agentmain} to configure the entitlement system,
6028 * instantiate and configure an {@link EntitlementChecker},
@@ -108,149 +76,11 @@ private static PolicyManager createPolicyManager() {
10876 Map <String , Policy > pluginPolicies = bootstrapArgs .pluginPolicies ();
10977 PathLookup pathLookup = bootstrapArgs .pathLookup ();
11078
111- List <Scope > serverScopes = new ArrayList <>();
112- List <FileData > serverModuleFileDatas = new ArrayList <>();
113- Collections .addAll (
114- serverModuleFileDatas ,
115- // Base ES directories
116- FileData .ofBaseDirPath (PLUGINS , READ ),
117- FileData .ofBaseDirPath (MODULES , READ ),
118- FileData .ofBaseDirPath (CONFIG , READ ),
119- FileData .ofBaseDirPath (LOGS , READ_WRITE ),
120- FileData .ofBaseDirPath (LIB , READ ),
121- FileData .ofBaseDirPath (DATA , READ_WRITE ),
122- FileData .ofBaseDirPath (SHARED_REPO , READ_WRITE ),
123- // exclusive settings file
124- FileData .ofRelativePath (Path .of ("operator/settings.json" ), CONFIG , READ_WRITE ).withExclusive (true ),
125-
126- // OS release on Linux
127- FileData .ofPath (Path .of ("/etc/os-release" ), READ ).withPlatform (LINUX ),
128- FileData .ofPath (Path .of ("/etc/system-release" ), READ ).withPlatform (LINUX ),
129- FileData .ofPath (Path .of ("/usr/lib/os-release" ), READ ).withPlatform (LINUX ),
130- // read max virtual memory areas
131- FileData .ofPath (Path .of ("/proc/sys/vm/max_map_count" ), READ ).withPlatform (LINUX ),
132- FileData .ofPath (Path .of ("/proc/meminfo" ), READ ).withPlatform (LINUX ),
133- // load averages on Linux
134- FileData .ofPath (Path .of ("/proc/loadavg" ), READ ).withPlatform (LINUX ),
135- // control group stats on Linux. cgroup v2 stats are in an unpredicable
136- // location under `/sys/fs/cgroup`, so unfortunately we have to allow
137- // read access to the entire directory hierarchy.
138- FileData .ofPath (Path .of ("/proc/self/cgroup" ), READ ).withPlatform (LINUX ),
139- FileData .ofPath (Path .of ("/sys/fs/cgroup/" ), READ ).withPlatform (LINUX ),
140- // // io stats on Linux
141- FileData .ofPath (Path .of ("/proc/self/mountinfo" ), READ ).withPlatform (LINUX ),
142- FileData .ofPath (Path .of ("/proc/diskstats" ), READ ).withPlatform (LINUX )
143- );
144- if (pathLookup .pidFile () != null ) {
145- serverModuleFileDatas .add (FileData .ofPath (pathLookup .pidFile (), READ_WRITE ));
146- }
147-
148- Collections .addAll (
149- serverScopes ,
150- new Scope (
151- "org.elasticsearch.base" ,
152- List .of (
153- new CreateClassLoaderEntitlement (),
154- new FilesEntitlement (
155- List .of (
156- // TODO: what in es.base is accessing shared repo?
157- FileData .ofBaseDirPath (SHARED_REPO , READ_WRITE ),
158- FileData .ofBaseDirPath (DATA , READ_WRITE )
159- )
160- )
161- )
162- ),
163- new Scope ("org.elasticsearch.xcontent" , List .of (new CreateClassLoaderEntitlement ())),
164- new Scope (
165- "org.elasticsearch.server" ,
166- List .of (
167- new ExitVMEntitlement (),
168- new ReadStoreAttributesEntitlement (),
169- new CreateClassLoaderEntitlement (),
170- new InboundNetworkEntitlement (),
171- new LoadNativeLibrariesEntitlement (),
172- new ManageThreadsEntitlement (),
173- new FilesEntitlement (serverModuleFileDatas )
174- )
175- ),
176- new Scope ("java.desktop" , List .of (new LoadNativeLibrariesEntitlement ())),
177- new Scope ("org.apache.httpcomponents.httpclient" , List .of (new OutboundNetworkEntitlement ())),
178- new Scope (
179- "org.apache.lucene.core" ,
180- List .of (
181- new LoadNativeLibrariesEntitlement (),
182- new ManageThreadsEntitlement (),
183- new FilesEntitlement (List .of (FileData .ofBaseDirPath (CONFIG , READ ), FileData .ofBaseDirPath (DATA , READ_WRITE )))
184- )
185- ),
186- new Scope ("org.apache.lucene.misc" , List .of (new FilesEntitlement (List .of (FileData .ofBaseDirPath (DATA , READ_WRITE ))))),
187- new Scope (
188- "org.apache.logging.log4j.core" ,
189- List .of (new ManageThreadsEntitlement (), new FilesEntitlement (List .of (FileData .ofBaseDirPath (LOGS , READ_WRITE ))))
190- ),
191- new Scope (
192- "org.elasticsearch.nativeaccess" ,
193- List .of (new LoadNativeLibrariesEntitlement (), new FilesEntitlement (List .of (FileData .ofBaseDirPath (DATA , READ_WRITE ))))
194- )
195- );
196-
197- // conditionally add FIPS entitlements if FIPS only functionality is enforced
198- if (Booleans .parseBoolean (System .getProperty ("org.bouncycastle.fips.approved_only" ), false )) {
199- // if custom trust store is set, grant read access to its location, otherwise use the default JDK trust store
200- String trustStore = System .getProperty ("javax.net.ssl.trustStore" );
201- Path trustStorePath = trustStore != null
202- ? Path .of (trustStore )
203- : Path .of (System .getProperty ("java.home" )).resolve ("lib/security/jssecacerts" );
204-
205- Collections .addAll (
206- serverScopes ,
207- new Scope (
208- "org.bouncycastle.fips.tls" ,
209- List .of (
210- new FilesEntitlement (List .of (FileData .ofPath (trustStorePath , READ ))),
211- new ManageThreadsEntitlement (),
212- new OutboundNetworkEntitlement ()
213- )
214- ),
215- new Scope (
216- "org.bouncycastle.fips.core" ,
217- // read to lib dir is required for checksum validation
218- List .of (new FilesEntitlement (List .of (FileData .ofBaseDirPath (LIB , READ ))), new ManageThreadsEntitlement ())
219- )
220- );
221- }
222-
223- var serverPolicy = new Policy (
224- "server" ,
225- bootstrapArgs .serverPolicyPatch () == null
226- ? serverScopes
227- : PolicyUtils .mergeScopes (serverScopes , bootstrapArgs .serverPolicyPatch ().scopes ())
228- );
229-
230- // agents run without a module, so this is a special hack for the apm agent
231- // this should be removed once https://github.com/elastic/elasticsearch/issues/109335 is completed
232- // See also modules/apm/src/main/plugin-metadata/entitlement-policy.yaml
233- List <Entitlement > agentEntitlements = List .of (
234- new CreateClassLoaderEntitlement (),
235- new ManageThreadsEntitlement (),
236- new SetHttpsConnectionPropertiesEntitlement (),
237- new OutboundNetworkEntitlement (),
238- new WriteSystemPropertiesEntitlement (Set .of ("AsyncProfiler.safemode" )),
239- new LoadNativeLibrariesEntitlement (),
240- new FilesEntitlement (
241- List .of (
242- FileData .ofBaseDirPath (LOGS , READ_WRITE ),
243- FileData .ofPath (Path .of ("/proc/meminfo" ), READ ),
244- FileData .ofPath (Path .of ("/sys/fs/cgroup/" ), READ )
245- )
246- )
247- );
248-
249- validateFilesEntitlements (pluginPolicies , pathLookup );
79+ FilesEntitlementsValidation .validate (pluginPolicies , pathLookup );
25080
25181 return new PolicyManager (
252- serverPolicy ,
253- agentEntitlements ,
82+ HardcodedEntitlements . serverPolicy ( pathLookup . pidFile (), bootstrapArgs . serverPolicyPatch ()) ,
83+ HardcodedEntitlements . agentEntitlements () ,
25484 pluginPolicies ,
25585 EntitlementBootstrap .bootstrapArgs ().scopeResolver (),
25686 EntitlementBootstrap .bootstrapArgs ().sourcePaths (),
@@ -260,74 +90,6 @@ private static PolicyManager createPolicyManager() {
26090 );
26191 }
26292
263- // package visible for tests
264- static void validateFilesEntitlements (Map <String , Policy > pluginPolicies , PathLookup pathLookup ) {
265- Set <Path > readAccessForbidden = new HashSet <>();
266- pathLookup .getBaseDirPaths (PLUGINS ).forEach (p -> readAccessForbidden .add (p .toAbsolutePath ().normalize ()));
267- pathLookup .getBaseDirPaths (MODULES ).forEach (p -> readAccessForbidden .add (p .toAbsolutePath ().normalize ()));
268- pathLookup .getBaseDirPaths (LIB ).forEach (p -> readAccessForbidden .add (p .toAbsolutePath ().normalize ()));
269- Set <Path > writeAccessForbidden = new HashSet <>();
270- pathLookup .getBaseDirPaths (CONFIG ).forEach (p -> writeAccessForbidden .add (p .toAbsolutePath ().normalize ()));
271- for (var pluginPolicy : pluginPolicies .entrySet ()) {
272- for (var scope : pluginPolicy .getValue ().scopes ()) {
273- var filesEntitlement = scope .entitlements ()
274- .stream ()
275- .filter (x -> x instanceof FilesEntitlement )
276- .map (x -> ((FilesEntitlement ) x ))
277- .findFirst ();
278- if (filesEntitlement .isPresent ()) {
279- var fileAccessTree = FileAccessTree .withoutExclusivePaths (filesEntitlement .get (), pathLookup , null );
280- validateReadFilesEntitlements (pluginPolicy .getKey (), scope .moduleName (), fileAccessTree , readAccessForbidden );
281- validateWriteFilesEntitlements (pluginPolicy .getKey (), scope .moduleName (), fileAccessTree , writeAccessForbidden );
282- }
283- }
284- }
285- }
286-
287- private static IllegalArgumentException buildValidationException (
288- String componentName ,
289- String moduleName ,
290- Path forbiddenPath ,
291- FilesEntitlement .Mode mode
292- ) {
293- return new IllegalArgumentException (
294- Strings .format (
295- "policy for module [%s] in [%s] has an invalid file entitlement. Any path under [%s] is forbidden for mode [%s]." ,
296- moduleName ,
297- componentName ,
298- forbiddenPath ,
299- mode
300- )
301- );
302- }
303-
304- private static void validateReadFilesEntitlements (
305- String componentName ,
306- String moduleName ,
307- FileAccessTree fileAccessTree ,
308- Set <Path > readForbiddenPaths
309- ) {
310-
311- for (Path forbiddenPath : readForbiddenPaths ) {
312- if (fileAccessTree .canRead (forbiddenPath )) {
313- throw buildValidationException (componentName , moduleName , forbiddenPath , READ );
314- }
315- }
316- }
317-
318- private static void validateWriteFilesEntitlements (
319- String componentName ,
320- String moduleName ,
321- FileAccessTree fileAccessTree ,
322- Set <Path > writeForbiddenPaths
323- ) {
324- for (Path forbiddenPath : writeForbiddenPaths ) {
325- if (fileAccessTree .canWrite (forbiddenPath )) {
326- throw buildValidationException (componentName , moduleName , forbiddenPath , READ_WRITE );
327- }
328- }
329- }
330-
33193 /**
33294 * If bytecode verification is enabled, ensure these classes get loaded before transforming/retransforming them.
33395 * For these classes, the order in which we transform and verify them matters. Verification during class transformation is at least an
0 commit comments