AWS Java SDK SSL Certificates
Asked Answered
L

4

8

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?

Lothians answered 22/6, 2020 at 7:31 Comment(0)
L
1

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.

Lothians answered 23/6, 2020 at 8:51 Comment(3)
How did you link it? I am going through the same problemSubtreasury
@GabrielRobaina Maybe #2139440?Choral
I don't recall from the top of my head as it's been a while now :/Choral
B
5

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.

Baras answered 14/10, 2021 at 12:8 Comment(1)
The default password is changeit not chageit if anyone is having trouble with thatHeisel
L
1

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.

Lothians answered 23/6, 2020 at 8:51 Comment(3)
How did you link it? I am going through the same problemSubtreasury
@GabrielRobaina Maybe #2139440?Choral
I don't recall from the top of my head as it's been a while now :/Choral
S
1

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.

Schuss answered 24/11, 2021 at 14:46 Comment(1)
Thx, is this possible in AWS S3 Java SDK 2.x, and code reference please?Aestival
S
0

For AWS SDK for Java 2.x:

  1. 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>
    
  2. Use your own implementation to build a TrustManager (e.g. this SO question)

    TrustManager tm = getTrustManager(truststorePath, Password);  // TODO
    
  3. Add the TrustManager in your client

    S3Client client = S3Client.builder()
            .region(region)
            .credentialsProvider(StaticCredentialsProvider.create(credentials))
            .httpClientBuilder(
                    ApacheHttpClient.builder()
                            .tlsTrustManagersProvider(() -> new TrustManager[]{tm})
            )
            .build();
    
Species answered 26/9, 2024 at 9:10 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.