Can't use Amazon S3 API over SSL? - java

I'm trying to use Amazon S3 API to encrypt and upload a file.
public class AmazonS3 {
String KmsId = "my_id_comes_here";
private TransferManager getTransferManager() {
AWSCredentials awsCredentials = new ProfileCredentialsProvider().getCredentials();
KMSEncryptionMaterialsProvider materialProvider = new KMSEncryptionMaterialsProvider(KmsId);
AmazonS3EncryptionClient s3Client = new AmazonS3EncryptionClient(awsCredentials, materialProvider,
new CryptoConfiguration().withKmsRegion(Regions.EU_CENTRAL_1)).withRegion(Regions.EU_CENTRAL_1);
s3Client.setEndpoint("s3.eu-central-1.amazonaws.com");
TransferManager transferManager = new TransferManager(s3Client);
return transferManager;
}
public void upload(String bucket, String keyName, String filePath)
throws InterruptedException, NoSuchAlgorithmException, IOException, InvalidKeySpecException {
TransferManager transferManager = getTransferManager();
// TransferManager processes all transfers asynchronously, so this call will return immediately.
Upload upload = transferManager.upload(bucket, keyName, new File(filePath));
try {
// Or you can block and wait for the upload to finish
upload.waitForCompletion();
System.out.println("Upload complete.");
} catch (AmazonClientException amazonClientException) {
System.out.println("Unable to upload file, upload was aborted.");
amazonClientException.printStackTrace();
}
}
Which works fine if I don't pass my trustore as arguments to my application.
But, if I initialize my application with my trustore like this:
-Dspring.profiles.active="dev" -Djavax.net.debug=all -Djavax.net.ssl.trustStore=/usr/share/ca-certificates/anevis/java/activemq/client.ts -Djavax.net.ssl.trustStorePassword=changeit
It gives me this error:
com.amazonaws.AmazonClientException: 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
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:516)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:317)
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3595)
at com.amazonaws.services.s3.AmazonS3Client.getObjectMetadata(AmazonS3Client.java:999)
at com.amazonaws.services.s3.transfer.TransferManager.doDownload(TransferManager.java:779)
at com.amazonaws.services.s3.transfer.TransferManager.download(TransferManager.java:691)
at com.anevis.documentengine.configuration.jms.AmazonS3.download(AmazonS3.java:57)
at com.anevis.documentengine.configuration.jms.S3UploadTest.testUpload(S3UploadTest.java:25)
at com.anevis.documentengine.configuration.jms.S3UploadTest.main(S3UploadTest.java:9)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:535)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:403)
at com.amazonaws.http.conn.ssl.SdkTLSSocketFactory.connectSocket(SdkTLSSocketFactory.java:128)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:304)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:611)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:446)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:749)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:505)
... 13 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
... 32 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:146)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 38 more
How can I fix this error ?

Your trust store doesn't have the certificate authority that secures the AWS APIs. You need to create a new trust store that combines client.ts with the ones required for AWS. The easiest way to do this is to merge client.ts with the cacerts keystore from the JRE.
Example:
keytool -importkeystore -srckeystore client.ts -destkeystore combined.ts -srcstorepass changeit -deststorepass changeit
keytool -importkeystore -srckeystore $JAVA_HOME/jre/lib/security/cacerts -destkeystore combined.ts -srcstorepass changeit -deststorepass changeit
Then use combined.ts instead of client.ts.

Thank you, we had similar problem but I tweaked response a little bit for our scenario.
I received this com.amazonaws.AmazonClientException: 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
exception when trying to connect to AmazonDynamoDB.
When we moved our application to HTTPS we started receiving this error.
So the solution was the same, the only difference was instead of client.ts I had to add certificate into cacerts which was generated during HTTPS migration.
keytool -importkeystore -srckeystore $JAVA_HOME/jre/lib/security/cacerts -destkeystore test.p12 -srcstorepass changeit -deststorepass test;
Thanks,

Related

sun.security.validator.ValidatorException:PKIX path building failed

I am trying to reach an external API through a secured connection. The connection usually requires a client certificate issued by the company. The certificate has been whitelisted and I also checked with Postman by importing the certificate and it worked fine. I am getting sun.security.validator.ValidatorException when I try to reach the API.
I generated these files using the .crt file:
trustStore.jks-
"C:\Program Files\Java\jdk1.8.0_341\bin\keytool" -import -file "C:/Users/user/certs/example.crt" -alias exampleCA -keystore "C:/Users/user/certs/truststore.jks"
2.keyStore.p12-
openssl pkcs12 -export -in "C:/Users/user/certs/example.crt" -inkey "C:/Users/user/certs/example.key" -certfile "C:/Users/user/certs/example.crt" -name "examplecert" -out "C:/Users/user/certs/keystore.p12"
3.keystore.jks-
"C:\Program Files\Java\jdk1.8.0_341\bin\keytool" -importkeystore -srckeystore "C:/Users/user/certs/keystore.p12" -srcstoretype pkcs12 -destkeystore "C:/Users/user/certs/keystore.jks" -deststoretype JKS
I have the keyStore setup in properties:
server.port=443
server.use-forwarded-headers=true
security.require-ssl=true
server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password= password
server.ssl.key-alias=examplecert
When I hit the url, I can see the same cert being used with httpsnot-secure error
However, when I click in the background 'thisisunsafe' as mentioned here stackoverflow-answer, I get the error:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target] with root cause
Can someone help me in this? I am completely new to SpringBoot.

Java not able to validate certificate even if certificate valid in browser

I have one GET API to call using java and I have used feign client to call this API.
When I call this API it is giving the error:
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
at java.base/sun.security.validator.Validator.validate(Validator.java:264)
at java.base/sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:313)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:222)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:129)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1323)
... 18 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
When I hit the same API in the browser, it is working fine. Browser doesn't display like an untrusted connection.
certificate information from firefox:
I am running my application in docker image openjdk:11-slim.
Why java is not able to validate the certificate even if the certificate is valid?
This may be because they are not added to your cacerts -
You can try running installCerts from below link, for the URL of site which you are trying to downlaod certificate from or which is not being allowed to access because of certificate issue.
java --source 11 InstallCert.java
https://github.com/escline/InstallCert
If it is self signed certificate, try below in your DockerFile -
FROM openjdk:11-jdk-slim
WORKDIR /opt/workdir/
#.crt file in the same folder as your Dockerfile
ARG CERT="certificate.crt"
#import cert into java
COPY $CERT /opt/workdir/
RUN keytool -importcert -file $CERT -alias $CERT -cacerts -storepass changeit -noprompt
If you have the .cer file, which you can otherwise export from browser. Add below to your DockerFile. So the required certs are available before ssl handshake. -
ADD your_ca_root.crt /usr/local/share/ca-certificates/foo.crt
RUN chmod 644 /usr/local/share/ca-certificates/foo.crt && update-ca-certificates

Spring http client: pkcs12 keystore and trustsrtore on httpclient

Into my application I'm using an HttpClient setting an ssl context:
#Bean
public HttpClient httpClient() throws Exception {
SSLContext sslContext = SSLContextBuilder.create()
.loadKeyMaterial(
new URL(schedulerConfiguration.getKeyStore()),
schedulerConfiguration.getKeyStorePassword().toCharArray(),
schedulerConfiguration.getKeyPassword().toCharArray()
)
.loadTrustMaterial(
new URL(schedulerConfiguration.getTrustStore()),
schedulerConfiguration.getTrustStorePassword().toCharArray()
)
.build();
return HttpClients.custom().setSSLContext(sslContext).build();
}
As you can see I'm loading a keystore and a truststore.
keystore contains the private key and truststore contains all chain certificates.
I'm running against client connections can't be launched due to:
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://balancer:8080/token": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I've built my jks from a .p12 file like this.
In order to build trsutstore:
$ openssl pkcs12 -in fitxers.p12 -nokeys -out cacerts-nokeys.crt
$ keytool -importcert -file cacerts-nokeys.crt -keystore cacerts-pre-splitted.jks
And in order to create my keystore:
$ keytool -importkeystore -srckeystore fitxers.p12 -srcstoretype pkcs12 -destkeystore auth-backoffice-pre.jks -deststoretype jks
Any ideas about what's wrong?
I remember having similar issue when not using aliases properly. Are you using aliases in your original p12 file? If so, I'd recommend using the other method for loading the key material with custom PrivateKeyStrategy.
Also take a look when trying to connect your client with vm option:
-Djavax.net.debug=all
You will be able to see a bit of more information. Hopefully this guides you to your solution!

SSLHandshakeException cannot authenticate user

I get this error while launching the application.
org.jboss.mq.SpyJMSException: Cannot authenticate user; - nested throwable: (javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target)
org.jboss.mq.SpyJMSException: Cannot authenticate user; - nested throwable: (javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target)
I set my certificate path by System.setProperty("javax.net.ssl.trustStore", "Path to certificate)..
But this is not working me..Also I have imported the certificate to the "cacerts" of Java Home. But still I am getting the error..
Any help would be appericiated...
The application authenticating the user has a Java keystore as its trust store. The trust store has to contain (as a trusted certificate) the certificate authority that signed the user's certificate. Put the certificate authority in a base-64 ca.cer file and use keytool -import -keystore YourKeystore -alias ca -file ca.cer -trustcacerts.

Still getting SunCertPathBuilderException after importing certificate

i am trying to connect to ldap server over ssl, and i got the server certificate and installed it as follows:
keytool -keystore cacerts -importcert -alias ldapCert -file LdapCert.cer
and i got certificate was installed successfully message, and i can verify that certificate was installed with the command:
keytool -list -keystore cacerts
and i can find my certificate in the list of trusted certificates.
here's how i am connecting to ldap server:
String host = "server.ip.here;
String userDN = "CN=myuser,OU=EmployeesOU,OU=MainOU,dc=mydomain,dc=net";
String userPassword = "mypassword";
boolean ssl = true;
public static LdapContext connectToLdap(String host,
String userDN, String userPassword,
boolean ssl) throws Exception {
System.out.println("connectToLdap");
String hostPrefix = "ldap";
String ldapPort = "389";
if (ssl) {
hostPrefix = "ldaps";
ldapPort = "636";
}
String providerUrl = hostPrefix + "://" + host + ":" + ldapPort;
//System.out.println("####### LDAP URL: " + providerUrl);
LdapContext ldapContext;
Hashtable<String, String> ldapEnv = new Hashtable<String, String>(11);
ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
ldapEnv.put(Context.PROVIDER_URL, providerUrl);
ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
ldapEnv.put(Context.SECURITY_PRINCIPAL, userDN);
ldapEnv.put(Context.SECURITY_CREDENTIALS, userPassword);
ldapEnv.put("com.sun.jndi.ldap.read.timeout", 1000 * 10 + "");
if (ssl) {
ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
}
ldapEnv.put(Context.REFERRAL, "ignore");
try {
ldapContext = new InitialLdapContext(ldapEnv, null);
System.out.println("success connection to ldap");
return ldapContext;
} catch (Exception e) {
System.out.println("failure connection to ldap");
e.printStackTrace();
return null;
}
}
after installing the certificate from cmd, and trying to run the application i am still getting the exception:
javax.naming.CommunicationException: simple bind failed: server.ip:636 [Root exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:197)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2694)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:293)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.init(InitialContext.java:223)
at javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:134)
at ldap.LDAPUtils.connectToLdap(LDAPUtils.java:58)
at Test.main(Test.java:43)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1623)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:198)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:192)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1074)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:128)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:465)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1120)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:744)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
at com.sun.jndi.ldap.Connection.run(Connection.java:808)
at java.lang.Thread.run(Thread.java:619)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:325)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:219)
at sun.security.validator.Validator.validate(Validator.java:218)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1053)
... 12 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:320)
i tried to use the disableCertificateValidation method before connecting to ldap as in the post Java client certificates over HTTPS/SSL
but it also gives same exception.
please advise why i am still getting this error.
You shouldn't modify the cacerts file that comes with the JDK. Copy it and add the certificate to your own file, and tell JSSE about it via the system property javax.net.ssl.trustStore.
Cause 1: having two conflicting installations of JDK, removed one of them and re imported the key and everything worked fine.
Cause 2: on some test machine i had to copy the generated cacerts file from
java/jdk/jre/lib/security into java/jre/lib/security
Cause 3: if you are running the code on websphere server you have to configure key store and certificates from wensphere as mentioned here:
http://www-01.ibm.com/support/docview.wss?uid=swg21316850

Categories