Description
Describe the bug
Elasticsearch uses the JVM Security Manager to restrict the files to which it has access, and in particular will block access to files in $HOME/.aws
by default. The v1 SDK (e.g. version 1.12.270
) treats this as if the files do not exist, which is what we want, but the v2 SDK (e.g. version 2.28.13
) apparently just fails if the Security Manager denies this access:
java.security.AccessControlException: access denied ("java.io.FilePermission" "/Users/davidturner/.aws/credentials" "read")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:488) ~[?:?]
at java.security.AccessController.checkPermission(AccessController.java:1085) ~[?:?]
at java.lang.SecurityManager.checkPermission(SecurityManager.java:411) ~[?:?]
at java.lang.SecurityManager.checkRead(SecurityManager.java:742) ~[?:?]
at sun.nio.fs.UnixPath.checkRead(UnixPath.java:840) ~[?:?]
at sun.nio.fs.UnixFileSystemProvider.readAttributesIfExists(UnixFileSystemProvider.java:183) ~[?:?]
at java.nio.file.Files.isRegularFile(Files.java:2370) ~[?:?]
at software.amazon.awssdk.profiles.ProfileFileLocation.lambda$resolveIfExists$2(ProfileFileLocation.java:90) ~[profiles-2.28.13.jar:?]
at java.util.Optional.filter(Optional.java:218) ~[?:?]
at software.amazon.awssdk.profiles.ProfileFileLocation.resolveIfExists(ProfileFileLocation.java:90) ~[profiles-2.28.13.jar:?]
at software.amazon.awssdk.profiles.ProfileFileLocation.credentialsFileLocation(ProfileFileLocation.java:77) ~[profiles-2.28.13.jar:?]
at software.amazon.awssdk.profiles.ProfileFile.addCredentialsFile(ProfileFile.java:151) ~[profiles-2.28.13.jar:?]
at software.amazon.awssdk.utils.builder.SdkBuilder.applyMutation(SdkBuilder.java:61) ~[utils-2.28.13.jar:?]
at software.amazon.awssdk.profiles.ProfileFile.defaultProfileFile(ProfileFile.java:99) ~[profiles-2.28.13.jar:?]
at software.amazon.awssdk.core.retry.RetryMode$Resolver.fromProfileFile(RetryMode.java:183) ~[sdk-core-2.28.13.jar:?]
at software.amazon.awssdk.core.retry.RetryMode$Resolver.lambda$resolve$0(RetryMode.java:171) ~[sdk-core-2.28.13.jar:?]
at software.amazon.awssdk.utils.OptionalUtils.firstPresent(OptionalUtils.java:47) ~[utils-2.28.13.jar:?]
at software.amazon.awssdk.core.retry.RetryMode$Resolver.resolve(RetryMode.java:171) ~[sdk-core-2.28.13.jar:?]
at software.amazon.awssdk.core.retry.RetryMode.defaultRetryMode(RetryMode.java:119) ~[sdk-core-2.28.13.jar:?]
at software.amazon.awssdk.awscore.retry.AwsRetryStrategy.defaultRetryStrategy(AwsRetryStrategy.java:45) ~[aws-core-2.28.13.jar:?]
at software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder.lambda$setOverrides$3(AwsDefaultClientBuilder.java:213) ~[aws-core-2.28.13.jar:?]
at java.util.Optional.ifPresent(Optional.java:178) ~[?:?]
at software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder.setOverrides(AwsDefaultClientBuilder.java:212) ~[aws-core-2.28.13.jar:?]
at software.amazon.awssdk.core.client.builder.SdkDefaultClientBuilder.syncClientConfiguration(SdkDefaultClientBuilder.java:199) ~[sdk-core-2.28.13.jar:?]
at software.amazon.awssdk.services.ec2.DefaultEc2ClientBuilder.buildClient(DefaultEc2ClientBuilder.java:36) ~[ec2-2.28.13.jar:?]
at software.amazon.awssdk.services.ec2.DefaultEc2ClientBuilder.buildClient(DefaultEc2ClientBuilder.java:25) ~[ec2-2.28.13.jar:?]
at software.amazon.awssdk.core.client.builder.SdkDefaultClientBuilder.build(SdkDefaultClientBuilder.java:173) ~[sdk-core-2.28.13.jar:?]
at java.security.AccessController.doPrivileged(AccessController.java:319) ~[?:?]
at org.elasticsearch.discovery.ec2.SocketAccess.doPrivileged(SocketAccess.java:32) ~[main/:?]
at org.elasticsearch.discovery.ec2.AwsEc2ServiceImpl.buildClient(AwsEc2ServiceImpl.java:90) ~[main/:?]
at org.elasticsearch.discovery.ec2.AwsEc2ServiceImpl.buildClient(AwsEc2ServiceImpl.java:45) ~[main/:?]
at org.elasticsearch.discovery.ec2.AwsEc2ServiceImpl.lambda$refreshAndClearCache$3(AwsEc2ServiceImpl.java:123) ~[main/:?]
at org.elasticsearch.common.util.LazyInitializable.maybeCompute(LazyInitializable.java:93) ~[elasticsearch-9.0.0-SNAPSHOT.jar:9.0.0-SNAPSHOT]
at org.elasticsearch.common.util.LazyInitializable.getOrCompute(LazyInitializable.java:71) ~[elasticsearch-9.0.0-SNAPSHOT.jar:9.0.0-SNAPSHOT]
at org.elasticsearch.discovery.ec2.AwsEc2ServiceImpl.client(AwsEc2ServiceImpl.java:113) ~[main/:?]
at org.elasticsearch.discovery.ec2.AwsEc2SeedHostsProvider.fetchDynamicNodes(AwsEc2SeedHostsProvider.java:101) ~[main/:?]
at org.elasticsearch.discovery.ec2.AwsEc2SeedHostsProvider$TransportAddressesCache.refresh(AwsEc2SeedHostsProvider.java:224) ~[main/:?]
at org.elasticsearch.discovery.ec2.AwsEc2SeedHostsProvider$TransportAddressesCache.refresh(AwsEc2SeedHostsProvider.java:216) ~[main/:?]
at org.elasticsearch.common.util.SingleObjectCache.getOrRefresh(SingleObjectCache.java:43) ~[elasticsearch-9.0.0-SNAPSHOT.jar:9.0.0-SNAPSHOT]
at org.elasticsearch.discovery.ec2.AwsEc2SeedHostsProvider.getSeedAddresses(AwsEc2SeedHostsProvider.java:93) ~[main/:?]
at org.elasticsearch.discovery.ec2.Ec2DiscoveryTests.buildDynamicHosts(Ec2DiscoveryTests.java:156) ~[test/:?]
at org.elasticsearch.discovery.ec2.Ec2DiscoveryTests.buildDynamicHosts(Ec2DiscoveryTests.java:85) ~[test/:?]
at org.elasticsearch.discovery.ec2.Ec2DiscoveryTests.testDefaultSettings(Ec2DiscoveryTests.java:169) ~[test/:?]
Regression Issue
- Select this option if this issue appears to be a regression.
Expected Behavior
We expect software.amazon.awssdk.profiles.ProfileFileLocation#resolveIfExists
to catch a SecurityException
and convert it into Optional.empty()
. The API docs for java.nio.file.Files#isRegularFile
and java.nio.file.Files#isReadable
both explicitly mention the possibility of throwing a SecurityException
rather than just returning false
if the file is nonexistent or unreadable.
Current Behavior
Instead software.amazon.awssdk.profiles.ProfileFileLocation#resolveIfExists
does not catch any exceptions and instead treats a SecurityException
similar to any other failure.
Stack trace is shown above.
Reproduction Steps
Somewhat tricky because it involves running the JVM with the Security Manager installed. If the description above is unclear then please let me know and I'll put more effort in here.
Possible Solution
diff --git a/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileFileLocation.java b/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileFileLocation.java
index 5b97526dae7..d53e460234e 100644
--- a/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileFileLocation.java
+++ b/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileFileLocation.java
@@ -87,6 +87,10 @@ public final class ProfileFileLocation {
}
private static Optional<Path> resolveIfExists(Path path) {
- return Optional.ofNullable(path).filter(Files::isRegularFile).filter(Files::isReadable);
+ try {
+ return Optional.ofNullable(path).filter(Files::isRegularFile).filter(Files::isReadable);
+ } catch (SecurityException e) {
+ return Optional.empty();
+ }
}
}
Additional Information/Context
We are aware that the Security Manager is deprecated and will not be available in a future JDK version. We are working to replace it with an alternative implementation that will maintain the same protections, which we therefore expect to suffer the same problems.
AWS Java SDK version used
2.28.13
JDK version used
21+35-2513 (Oracle)
Operating System and version
Mac OS X 15.2 (aarch64)