Reputation: 1416
I have a JBoss AS7 connecting to AWS and specifically to S3 over the AWS SDK for Java, I have the access and secret keys, and everything runs fine. I use the S3 for various file sharing.
The JBoss' datasource connects to AWS RDS. I've enabled SSL encryption for the datasource - I have the rds-ca-2019-root.pem
in my truststore configured in my standalone.xml, and my RDS datasource connects and verifies the SSL with no problem.
However, when I try to connect to S3 over the SDK (when the truststore with the RDS cert is enabled), I get the following exception:
Caused by: com.amazonaws.SdkClientException: Unable to execute HTTP request: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
So, no truststore enabled: I can connect to S3 through SDK just fine. When I enable the truststore with the RDS certificate: my SDK -> S3 connection breaks.
I can't figure out what certificate I need to add to the truststore so that the SDK can work, or do I need to configure the SDK to use TLS somehow?
Upvotes: 8
Views: 15664
Reputation: 17085
For AWS SDK for Java 2.x:
Allow client configuration by adding apache-client dependency (as explained in the official docs)
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>${awssdk.version}</version>
</dependency>
<!-- By adding the apache-client dependency, ApacheHttpClient will be added
to the compile classpath so you can configure it. -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
<version>${awssdk.version}</version>
</dependency>
Use your own implementation to build a TrustManager (e.g. this SO question)
TrustManager tm = getTrustManager(truststorePath, Password); // TODO
Add the TrustManager in your client
S3Client client = S3Client.builder()
.region(region)
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.httpClientBuilder(
ApacheHttpClient.builder()
.tlsTrustManagersProvider(() -> new TrustManager[]{tm})
)
.build();
Upvotes: 1
Reputation: 1611
Ognjen's answer helped me to troubleshoot this issue. I had same problem and the issue was due to AWS SDK using custom truststore that I built for RDS connection. I had specified the custom truststore by setting javax.net.ssl.trustStore
parameter explicitly.
The solution I applied:
I used the script in this documentation to import the rds-combined-ca-bundle.pem
into the $JAVA_HOME/lib/security/cacerts
(You may find this cacerts
file inside the jre/lib/security
folder if you have the JDK installed.). Then I removed the javax.net.ssl.trustStore
setting that I had. Then java started using the default cacerts
file and now all is good.
The default password for java default truststore is changeit
.
Upvotes: 5
Reputation: 4285
Ognjen and Asanka propose to use the same truststore for whole application (or application server) that is not suitable in some cases. But AWS Java SDK provides ApacheHttpClientConfig
via ClientConfiguration
to affect Apache HTTP client, e.g.:
import com.amazonaws.ApacheHttpClientConfig;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.http.conn.ssl.SdkTLSSocketFactory;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import org.apache.http.conn.socket.ConnectionSocketFactory;
SSLContext myContext = ...
HostnameVerifier myVerifier = ...
ConnectionSocketFactory factory = new SdkTLSSocketFactory(myContext, myVerifier);
ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.getApacheHttpClientConfig().setSslSocketFactory(factory);
AmazonS3 s3client = AmazonS3ClientBuilder.standard()
.withClientConfiguration(clientConfiguration)
.build();
Edit: See also StackOverflow question #47913449.
Upvotes: 1
Reputation: 1416
So I figured out what was wrong: not having any sort of custom truststore defined for my jboss meant that the AWS SDK pulled the regular cacerts truststore from $JAVA_HOME/lib/security/cacerts
. Defining my own truststore (which lacked all the certificates from the cacerts truststore) - meant that AWS SDK had nowhere to fetch the regular certificates.
So to solve it: I imported my rds-ca-2019-root.pem
into the above mentioned cacerts file and linked that as my server truststore in my standalone.xml.
Upvotes: 1