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?
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.
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.
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.
Related
I am running a local Spring boot app that uses oauth2.0 and ssl.
I am using a zerossl signed certificate which is stored in /src/main/resources, and I've imported into the keychain in the project resources.
I am able to retrieve a token and call the /oauth/check_token endpoint manually, however when I try to hit any other endpoint I get the following error:
.o.s.r.w.BearerTokenAuthenticationFilter : Authentication request for failed!
org.springframework.security.authentication.AuthenticationServiceException: I/O error on POST request for "https://localhost:8443/oauth/check_token": 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: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
application.properties:
# The format used for the keystore. It could be set to JKS in case it is a JKS file
server.ssl.key-store-type=PKCS12
# The path to the keystore containing the certificate
server.ssl.key-store=classpath:demo.p12
# The password used to generate the certificate
server.ssl.key-store-password=*****
# The alias mapped to the certificate
server.ssl.key-alias=demo
server.ssl.enabled=true
security.oauth2.resource.token-info-uri=https://localhost:8443/oauth/check_token
security.oauth2.client.registered-redirect-uri=https://localhost:8443/test
spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=https://localhost:8443/oauth/check_token
Stepping through the code it looks like when the NimbusOpaqueTokenIntrospector tries to check the token by calling POST https://localhost:8443/oauth/check_token it is not even hitting the endpoint (I placed a breakpoint in CheckTokenEndpoint controller) and getting the above KPIX error. I've tried using a custom RestTemplate that specifies the SSL context but I'm still seeing the same error.
If you are still struggling with this, I also experienced the same issue and also tried to install the Valid certificate into my JDK ca-certs. That was actually the correct solution except that even though both the RootCa and ActualDomain certs were installed as trusted certs in JDK ca-certs, there was an intermediate certificate issued just recently that I had left out. I installed the intermediate certificate as a trusted cert into the JDK ca-certs and the TLS certificate is no more.
RootCA=>!!!IntermediateCert!!!=>SubdomainCert
I am new in JAVA, Consuming web service(.wsdl) in Web Service Client project. I import the client certificate in java cacerts store in jrd. My code is as follows:
System.setProperty("javax.net.ssl.trustStore","[PATH]/cacerts.jks");
System.setProperty("javax.net.ssl.trustStorePassword","changeit");
ServicesProxy service = new ServicesProxy();
ServiceRequest request = new ServiceRequest(1498);
ServiceResponse response = service.getDetails(request);
I'm failed to handshake, I am getting the following exception:
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 have no clue why there is an exception. Any help will be appreciated.
You probably have to add the key chain in the certificate (PEM format).
CA Root -> Intermediate Cert -> Cert.
Or the certificate cannot be found in the keystore, do you use the correct alias etc.
And I do not recognize the SOAP JAX-WS implementation you use.
Not a solution to your problem, but maybe it helps to find it:
You can start your client with the VM parameter -Djavax.net.debug=all which will give you a lot of information about the SSL connection.
Check here for details about the output:
https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/ReadDebug.html
Use -Djavax.net.ssl.trustStore property directly instead.
One more thing the server you use in that also u need to place the jks for handshake.
For example server is JBoss then bin
I guess your cacert is not correct or the path is unaccessible. I followed the instructions given here
Use SSL Poke to verify connectivity
Download SSLPoke.class
Execute the class as follows, changing the URL and port:
$JAVA_HOME/bin/java SSLPoke yoururl 443
A successful connection would look like this:
$JAVA_HOME/bin/java SSLPoke yoururl 443
Successfully connected
Try to use a different truststore to connect
$JAVA_HOME/bin/java -Djavax.net.ssl.trustStore=[PATH]/cacerts.jks SSLPoke yoururl 443
If it fails the truststore does not contain the proper certificates.
How to solve it
The solution is extracted from here
Fetch the certificate again from the server:
openssl s_client -connect yoururl:443
You need openssl. Save the output to a file called public.crt. This is how your file should look like:
-----BEGIN CERTIFICATE-----
< Bunch of lines of your certificate >
-----END CERTIFICATE-----
Import the certificate:
$JAVA_HOME/bin/keytool -import -alias -keystore $JAVA_HOME/jre/lib/security/cacerts -file public.crt
Enter the password if prompted (the default is changeit)
Recommendation
In the same post it is not recommended to use a configured trustStore different than the JVM cacert because then java could not access other root certificates.
This is a quite common error while dealing with soap services over SSL, I've had it a few times.
Your certificate may not be correctly installed in your truststore.
You can use openssl to check and install the correct certificate in the truststore, as explained here
Hi Looks like certificates are not imported correctly or path used in code not pointing to correct keystore.
I hope following steps in below article will help you.
http://magicmonster.com/kb/prg/java/ssl/pkix_path_building_failed.html
I'm a bit lost of how I can use certificate in WidlFly 11. I re the doccumentation and found a lot of terms like JSSE, OpenSSL, Elytron, ApplicationRealm.
The problem occurs when I execute the code
final URL url = new URL("https://someUrl");
HttpsURLConnection httpURLConnection = (HttpsURLConnection)url.openConnection();
This exception is thrown sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
So, what exactly need to configure? I tried the section "Enable One-way SSL/TLS for Applications" in Elytron Doccumentation but didn't works.
ps: I'm using java 9.01
ps2: I'm using standalone-full.xml
let me know if you need more informations
This is unrelated to WildFly - you need to configure certificates trusted by java URL connections - you need to create and configure truststore:
create keystore containing certificate of server (if it is self-signed certificate), or better, certificate of its CA:
keytool -import -file myCA.cert -alias myCA -storepass mypassword -noprompt -keystore my.truststore
start using created keystore file as truststore in WildFly by setting javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword system properties:
bin/jboss-cli.sh -c
/system-property=javax.net.ssl.trustStore:add(value="/path/to/my.truststore")
/system-property=javax.net.ssl.trustStorePassword:add(value="mypassword")
Elytron documentation you mention is related only to server side - but this is client side configuration, which is not currently handled by it.
The certificate is not trusted, iirc there is a self-signed certificate in WildFly 11 so yo need to trust it or install a real certificate.
Accept server's self-signed ssl certificate in Java client
I tried to move from ldap to ldaps for Login authenticator.
In adapter.xml
<property name="ldapURL" defaultValue="ldap://10.10.10.10:10636" displayName="The LDAP Server URL"/>
In LoginAuthenticator class
env.put(Context.SECURITY_PROTOCOL, "ssl");
I get the following error.
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I do not know, where I need to put my keystore to hit in ldaps protocol. Can you please help me?
I tried putting it in the following path with server.xml configurations, but no luck.
E:\MobileFirst-8.0.0.0\mfp-server\usr\servers\mfp\resources\security
<sslDefault sslRef="mySSLSettings" />
<ssl id="mySSLSettings" keyStoreRef="LDAPKeyStore" clientAuthentication="true" />
<keyStore id="LDAPKeyStore" location="serverssl.ks" type="JKS" password="secret" />
As pointed out by marabu, if you add the CA certificates of your LDAP server to Liberty's trust store, it might solve your problem.
Where you need to add depends on how you have configured your trust store.
Going by the ssl configuration snippet you have pasted and assuming you have not defined the truststore via jvm.options or added it in MobileFoundation's keystore in MobileFoundation console, your serverssl.ks would act as both keystore as well as trust store.
So if you add the CA certificates of your LDAP server to serverssl.ks and restart the server, it should work I feel.
You can add a CA certificate to your keystore by executing this command,
keytool -importcert -keystore serverssl.ks -alias <your_alias> -file <yourcacert.pem>
You wonder about the keystore, but the error message is about your truststore. The backend presents its (presumably self-signed certificate or a self-owned CA) certificate to your adapter during the SSL handshake. Your adapter tries to walk the chain of trust by looking for the issuers certificate recursively in your truststore.
Either you didn't import the backend certificate chain into your truststore or your adapter isn't using the truststore you configured.
Currently I try to make a play application be able to communicate SSL encrypted with the database.
I created self-signed certificate and CA for mysql. There is no problem with that normally, I can make the application communicate with the db server encrypted, when I add this CA to the JAVA_OPTS
-Djavax.net.ssl.trustStore=/app/path/conf/truststore
Everything goes well until my application not tries to communicate with other sites via SSL:
java.net.ConnectException: General SSLEngine problem to https://api.twitter.com/1/statuses/oembed.json?<meh>
[...]
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
[...]
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
[...]
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
[...]
The error is pretty obvious: twitter's ssl cert cannot be checked, because my truststore doesn't contains the CA which signed twitters certificate. IIRC I cannot add more than one "javax.net.ssl.trustStore" parameter for JVM, so I have to inject my CA's into the play framework. For luck, play framework supports ssl, and regarding the documentation I can add multiple truststores: https://www.playframework.com/documentation/2.4.x/WsSSL
I created a config file for ssl:
play.ws.ssl {
trustManager = {
stores = [
{ path: /path/to/truststore, type: "JKS", password = "<whatever is it" }
{ path: ${java.home}/lib/security/cacerts } # Default trust store
]
}
But when I start the server, I got the following error message:
Oops, cannot start the server.
java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
And now, I am stuck. I can inject my truststore for JVM, but when I do this, the app cannot communicate with other SSL enabled hosts - there's no cert, but when I try to add my truststore for play framework it doesn't accept it, because nobody signed my cert.
Is there a way to solve this somehow? I suspect if I take the system wide cacert file (which is used by java) and my truststore, and then I merge them with keytool, it will solve this, but this is not the best way - it would be more sane if I could pack my self signed certs next to the application.
I had the same problem for some reason my own trust store wouldn't be recognized so I ended up adding my certificate to the default keystore (${java.home}/lib/security/cacerts). You can use this command to do this (BTW cacerts default password is changeit):
keytool -v -importkeystore -srckeystore alice.p12 -srcstoretype PKCS12 -destkeystore "c:\Program Files\Java\jre1.8.0_71\lib\security\cacerts" -deststoretype JKS
Then you need to have the trustManager and the key manager defined. The trustManager points to the trust store and the keyManager to your certificate.
play.ws.ssl {
trustManager = {
stores = [
{
path: ${java.home}/lib/security/cacerts
}
]
}
keyManager = {
stores = [
{
type: "PKCS12",
path: "/Users/work/Documents/path/to/certificate/certificate.p12",
password: "pass"
}
]
}
}
That error means Play can't find the stores. Is the path correct?
I had the same error message: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty caused by empty store. According to Key store docs there could be password field in the configuration but it was ignored therefore certificates were not read from the store. I had to use PEM format or you can include certificates in config see Configure store. The password field is added/put back in commit #e867e729. I'm on Play 2.6 so I couldn't test it.