JDBC Certificate Requirements for connection in Google Apps Scripts - java

I'm trying to connect to an on-premises sql server (Microsoft Sql Server Express), but I keep getting an error that has to do with the validation of the certificate.
Connections through locally-run java (with JDBC) work when I pass encrypt=false or trustServerCertificate=true, otherwise I get an error message :
"Error: "PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target".
I know that Google Apps Scripts allows for using self-signed certificates (as documented here), but I'm not sure what they're actually looking for in the _serverSslCertificate, _clientSslCertificate, or _clientSslKey fields.
Unfortunately, I'm not able to share more details about the network I'm working in. I've tried applying self-signed certificates generated with PowerShell and Windows IIS to the server, but it simply doesn't restart after I do this.
Any help is appreciated.

These parameters require SSL certificates and key of the server and client. As documented here, you can see the expected values they need on those parameters. See snippet below:
var conn = Jdbc.getConnection('jdbc:mysql://<ip address>/<db name>?useSSL=true', {
user: '<user>',
password: '<pass>',
_serverSslCertificate: '-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----',
_clientSslCertificate: '-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----',
_clientSslKey: '-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----'
});
You can try the above snippet but this is for MySQL originally and is reported to have not worked for Microsoft SQL Server. The latter has its own issue posted here but still doesn't have any updates.
Guides that might help you are linked below.
References:
https://developers.google.com/apps-script/guides/jdbc
https://trang-nguyen-ngoc.medium.com/import-data-from-ms-sql-server-to-google-sheets-using-google-apps-script-d92098ea16ee (establish sql connection)

Related

Create a SSL connection between spring and nodejs apps locally

I have two apps, one is written in nodejs (which in this case is simple mock-server) and spring app (core app). I want to create a SSL connection between this two. Firstly I generated pair of key and cert, then simply setup a nodejs to work over SSL (I used this example: setting SSL - nodeJs).
I have checked that when I wrote in browser https://localhost:3000 it gives me a "secure" connection (with open padlock - so it's ok).
Next I was making a configuration on spring app using setting SSL - Spring. I took a cert from previous step generation and set it in keystore into .p12 file. In spring application I changed the url to node app to https.
When I try to connect from spring app and get some mock data from node I'm getting this stacktrace:
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I found something in stack but when I set this cert in specific directory and then restart my app, result is same.
Have anyone maybe a clue what could be wrong in this configuration and some suggestion how to fix it?
I found the solution of this problem. I don't know why, but when I created a keystore with cert inside and then use it in my spring app it cannot find this keystore with cert globally. I was looking for documentation about openJDK11 (because I used it) and find a link to Enabling Unlimited Strength Jurisdiction Policy and check file for which I have version of openJDK11.
In my case the line from crypto.policy was commented, don't know why. When I uncommented it and set unlimited it gives me one more error, but then I find one another solution. I found that, that I need to add my sign-self certificate to cacerts file (how to add my self-signed cert to cacerts). After this two operation it works as charm.

Postgresql JDBC SSL

We have a remote PostgreSQL DB server which requires SSL certs to be provided to connect to it.
I have the following certs with me.
root.pem
intermediate.pem
private-chain.pem
public-chain.pem
certificate.cer
certificate.key
And I am able to connect to the remote database using psql as
psql "port=5432 host=remote-host user=username sslcert=public-chain.pem sslkey=certificate.key dbname=database sslmode=require"
Now, I need to connect to the same database from a Java Spring based Rest API. So, ideally this would require building keystrokes from the certs and using that to connect to the the db.
The issue is, I'm not able to! I've tried all combinations of cert, public-chain, private-chain, root ca, etc. in the keystore. And I've tried passing the keystore as JVM arguments when calling the jar file (-Djavax.net.ssl.trustStore -Djavax.net.ssl.trustStorePassword -Djavax.net.ssl.keyStore -Djavax.net.ssl.keyStorePassword).
I've also tried pointing to the keystrokes from PostgreSQL JDBC connection string (jdbc:postgresql://remote-host:5432/database?ssl=true&sslcert='filename'&sslkey='key'). Not really sure if this is the right way.
But I keep getting this error.
Caused by: org.postgresql.util.PSQLException: FATAL: connection requires a valid client certificate
at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:473) ~[postgresql-42.2.2.jar!/:42.2.2]
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:205) ~[postgresql-42.2.2.jar!/:42.2.2]
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49) ~[postgresql-42.2.2.jar!/:42.2.2]
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195) ~[postgresql-42.2.2.jar!/:42.2.2]
at org.postgresql.Driver.makeConnection(Driver.java:452) ~[postgresql-42.2.2.jar!/:42.2.2]
at org.postgresql.Driver.connect(Driver.java:254) ~[postgresql-42.2.2.jar!/:42.2.2]
I am not able to figure out why it works with psql and not with jdbc.
EDIT 1:
Currently I am trying the following approach. This is the spring datasource configuration
spring.datasource.url=jdbc:postgresql://remote-host:5432/database?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory
spring.datasource.username=username
This is the cert config
export PGSSLCERT=/tmp/client.cer
export PGSSLKEY=/tmp/client.key
export PGSSLMODE=allow
I've also followed the steps described here to trust root ca. But I guess that is not necessary since I'm using org.postgresql.ssl.NonValidatingFactory
And I'm starting the application as
java -jar -Dspring.profiles.active=prod application.jar
Any insights into this are appreciated! Thanks.
What does your pb_hba.conf setting look like?
The JDBC driver only supports the trust, ident, password, md5, and crypt authentication methods.
So your java app will have to connect using password and certificate. You can specify that in your pb_hba.conf:
hostssl all all 0.0.0.0/0 md5 clientcert=1

com.ibm.jsse2.util.j: Certificate chaining error while accessing a page through https in notes agent

I have following situation - I want to get page content using https request and java agent. However, I'm getting following error message:
javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.j: Certificate chaining error
I already imported internet certificates to my local notes cacerts file, but nothing changed.
However, when I'm running same code in Eclipse, using keystore with certificates downloaded from page I try to receive and it works fine.
I'm out of ideas, any suggestions will be appreciated!
===EDIT===
Dmytro Pastovenskyi's answer helped me, but additionally to get rid of protocol_version exception I had to use following code, setting version of TLS used:
System.setProperty("https.protocols", "TLSv1");
It seems nessesary to establish connection to some sites using 1.6 IBM JAVA.
I had same issue some times before.
It looks like IBM Domino server more strict when it check certificates. Our administrator who at the beginning said that chain is correct later found an issue with chain (and yes, it worked for .NET/JAVA and other platform, just not with Domino). Try to find some online tools that verify chain.
Before chain is fixed you can simply disabled certificate validation. I've an article how to do it (+ some other articles that may help you). Have a look here: Disabling certificate validation in Java

Java mail TLS authentcation

I am trying to get a grasp on the fundamentals of Java Mail API and TLS. I have the following scenario:
There is an STMP server that uses TLS & SSL. If I log on to this server with some client, I can send authenticated &verified e-mails without any problems.
Then I try to run a web server on a different machine, that sends mail using the previously mentioned SMTP server. I still want to send TLS & SSL emails, however no matter how I configure the startup properties I get the following well known error:
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 found a lot of people having similar issues, however my question is this:
Considering the previuosly described scenario, do I have to get some kind of certificate to the web server (possible somewhere in the JRE), or should it just work fine since the mail server already has that certificate & authentication mechanizm running. Shouldn't it be possible to just use the certificate of the SMTP server? Anyway, if I have to install the certificate to the machine that uses the STMP server how can I get that certificate?
I'm pretty new to JavaMail API and I have seen lots of articles about this but I could not find the answer black & white for my question.
Your client (that is in your case the one running on the webserver) needs to verify the SSL certificate of the mail server. It seems that your java truststore doesn't contain that certificate.
So you either need to put that certificate into the default truststore of your JRE (what I wouldn't recommend) or define a different truststore for your application (that of course needs to contain the mail servers certificate). To do that set this VM parameter: Djavax.net.ssl.trustStore=<path-to-truststore>
Edit: Ah I missed some part of your question.
To get the certificate of the mail server use something like openssl. See for example:
https://serverfault.com/questions/139728/how-to-download-ssl-certificate-from-a-website
The answer is in the JavaMail FAQ.
Quoted text from the linked site:
Q: When connecting to my mail server over SSL I get an exception like "unable to find valid certification path to requested target".
A: Your server is probably using a test certificate or self-signed certificate instead of a certificate signed by a commercial Certificate Authority. You'll need to install the server's certificate into your trust store. The InstallCert program will help.
Alternatively, you can set the "mail.protocol.ssl.trust" property to the host name of your mail server. See the javadocs for the protocol provider packages for details.
Other common causes of this problem are:
There's a firewall or anti-virus program intercepting your request.
There's something wrong in your JDK installation preventing it from finding the certificates for the trusted certificate authorities.
You're running in an application server that has overridden the JDK's list of trusted certificate authorities.

Steps to trouble shoot SSL

I am trying to trouble shoot a two way SSL handshake mechanism. I get an 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
This indicates that one of my keystore or my truststore files does not have the appropriate entries. I know the way to trouble shoot this is to go to the server's truststore do the keytool list check the signing authorities and come to the client's key/truststore and verify this.
Can someone list these steps clearly (with the appropriate commands) please? Googling is not leading me anywhere. I just need a list of steps of "How can I confirm that Client X can talk to Server Y with two way SSL using Cert Z"?
The SunCertPathBuilderException exception is thrown whenever there the certificate validator fails to establish a chain between the certificate and a root certificate.
The easiest way to confirm that the certificate validates is to use a graphical tool like
Keyman, or
KeyTool IUI
The above tools are recommended since the exception is usually thrown in the absence of a root certificate.
If you want to examine what certificates are getting exchanged, it is better to switch on the ssl debug flag on the JVM node where the validation is failing.
Another option is to use a network traffic capture utility like Ethereal or Microsoft Netmon to obtain a dump of the traffic containing the certificate exchanges.
PS: Are you using the right keystore in the first place? I remember doing the same mistake many moons ago...

Categories