I'm trying to connect to SQL Server 13 in a Springboot 2.7.5 after upgrading java to version 17
This is the key points the stacktrace when the application starts up and attempts to connect
Failed to obtain JDBC Connection; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: \"Certificates do not conform to algorithm constraints\". ClientConnectionId:3dd8afba-ccaf-451e-a8f1-5687b548ee3b\
java.security.cert.CertPathValidatorException: Algorithm constraints check failed on keysize limits: RSA 1024 bit key used with certificate: CN={SERVER_URL}
I've tried to add encrypt=true and trustServerCertificate=true to the connection url and still get the same issue.
Looking at the SQL version compatbiity list: https://learn.microsoft.com/en-us/sql/connect/jdbc/microsoft-jdbc-driver-for-sql-server-support-matrix?view=sql-server-ver16
I should be able to use com.microsoft.sqlserver:mssql-jdbc:11.2.0.jre17 also downgrading major versions also get the same result.
I'm able to connect the server using the same creds using intellij thats configured to use java 17 and using driver 11.2.1
I figured out the issue, since RHEL8 it has removed weak crypto algorithms. So, I had to update the Docker file to have RUN update-crypto-policies --set LEGACY, see also https://access.redhat.com/articles/3642912
Related
I'm in the process of upgrading a java application. Originally, the application was built with jdk 8 and the server was jetty 9. Since upgrading to jetty 10 and jdk 11, I'm running into an issue when trying to make requests to our sql datasource. When the application attempts to query the database, it fails with the error:
java.sql.SQLException: Cannot create PoolableConnectionFactory
(The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target". ClientConnectionId:redacted)
at org.apache.commons.dbcp2.BasicDataSource.createPoolableConnectionFactory(BasicDataSource.java:653)
at org.apache.commons.dbcp2.BasicDataSource.createDataSource(BasicDataSource.java:531)
at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:731)
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:181)
I understand that either the jetty server or the sql server are missing a security certificate, but I'm not sure what to do about it. I read through the documentation here:
https://www.eclipse.org/jetty/documentation/jetty-10/operations-guide/index.html#og-keystore but the sql server is a remote server that I don't have admin access to, so I'm not sure I can even do what they describe. Do I need to get the certificate and key from the sql server somehow? What am I missing here?
Your program is failing because it is trying to connect to an "unsecure" location, you have to connect to the destination manually, get the certificate/or certificates, install them into your local keystore, and restart your program.
Some instructions on how to do that can be gound here.
https://www.thesslstore.com/knowledgebase/ssl-install/jetty-java-http-servlet-webserver-ssl-installation/
If you connect to multiple locations, yes, you need to have an entry for each, unless that they have a wildcard certificate (a certificate that applies for all of them).
Alternatively! (not sure but handy) you can start the connection without enforcing certificate validation, in this case the connection will happen no matter is the destination is actually false, this is a security issue, but there are cases when this is needed, in fact, this happens a lot when you run balancers where they validate the certs for you and you connect in http to them, automatically the validation is getting dropped since most of those balancers won't fail to connect even if the validation fails, but this is a different topic!
Cheers.
I am trying to connect to ms-sql database from java using jdk1.8.0_231 and fail with this exception:
The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "SQL Server did not return a response. The connection has been closed.
Does anyone know how to overcome this?
When I use 1.8.0_111, the connection is successful but I must use the 231 version since in my project I need to connect to other database with encrypted password that is not supported by the 111 version.
Any suggestions?
We are observing SQL Server connection is getting dropped with the below error
: com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "SQL Server returned an incomplete response. The connection has been closed. ClientConnectionId:b928e7b0-689b-40f8-be3e-158261d0a84a".
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "SQL Server returned an incomplete response. The connection has been closed. ClientConnectionId:b928e7b0-689b-40f8-be3e-158261d0a84a"
we are using sqljdbc42.jar in our application , MSSQL Server is MS SQL SERVER 2014 SP3 java version is 1.8
we cannot set to TLSv1 as mentioned in one of the resolution here SQL Server JDBC Error on Java 8: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption,
as a dependent application needs TLSv2 for it to work.
As per microsoft, jdbc 4.2 jar should resolve it , but we are already on it. https://blogs.msdn.microsoft.com/dataaccesstechnologies/2016/11/30/intermittent-jdbc-connectivity-issue-the-driver-could-not-establish-a-secure-connection-to-sql-server-by-using-secure-sockets-layer-ssl-encryption-error-sql-server-returned-an-incomplete-respons/
Please share suggestions or inputs you may have implemented for a similar problem.
Thanks,
Nivedita
Did you try the registry change mentioned in option 2 of the microsoft article?
Disable DHE cipher suites :
Warning: If you use Registry Editor incorrectly, you may cause serious problems that may require you to reinstall your operating system. Microsoft cannot guarantee that you can solve problems that result from using Registry Editor incorrectly. Use Registry Editor at your own risk.
Open Registry Editor.
Access key exchange algorithm settings by navigating to the following registry location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms
Select the Diffie-Hellman sub key (if it does not exist, then create
it).
Set the Enabled DWORD registry value to 0 (if it does not
exist, then create it).
Exit Registry Editor.
Impact of the workaround: Encrypted TLS sessions that rely on DHE keys will no longer function unless alternative failover options have been implemented.
https://technet.microsoft.com/en-us/library/security/ms15-055.aspx
I have built a JAVA web application which uses SOAP to fetch data from an external database server. This works fine until a few days ago. Now, the connection to the database server is terminated while establishing them.
In my JAVA log file, I found the following sequence of exceptions:
javax.net.ssl.SSLException: Server key
at sun.security.ssl.Handshaker.throwSSLException(Handshaker.java:1260)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:283)
...
Caused by: java.security.spec.InvalidKeySpecException: Unknown KeySpec type: java.security.spec.ECPublicKeySpec
at org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory.engineGeneratePublic(Unknown Source)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
Maybe the provider of the database server has changed their SSL certificate and got another CA chain.
I noticed that the intermediate CA use SHA384withRSA as signature algorithm. (see COMODO, Domain Validation (SHA-2)).
So, what can I do to to make my system running again?
Please ask, if you need further information.
Remark: The same SOAP request from a Windows 7 client works fine. There I noticed, that the Windows 7 client uses TLSv1.2 to establish the SSL connection. The Linux system of my server (see below) uses TLSv1 ,
The configuration of my Java WebServer:
Debian Wheezy
Java: OpenJDK 1.7.0u111
Tomcat 7.0.28
https connector uses JSSE with sslProtocol="TLS"
BIRT Runtime V4.5.0
DTP V1.12.0
org.eclipse.datatools.enablement.oda.ws V1.2.6
Thanks
Friedbert
Solved!
Apparently, the configuration of the tomcat connector did no longer match current security standards.
I had set up the system 2 years ago. But the security requirements have increased in the meantime.
Now I took a recent appliance from turnkey, compared the settings and found a few differences:
JAVA: java.security
security.provider.10=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg
Tomcat7: server.xml /Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
sslProtocol="TLSv1.2" sslEnabledProtocols="TLSv1.2,TLSv1.1,TLSv1"
server="Secret" URIEncoding="UTF-8" (may be, these does not matter)
With these changes, my system works again!
I'm trying to establish an SSL connection to a Sybase ASE 15.7 using JDBC driver with no luck.
I tried the following options:
Using JTDS 1.25 driver (jtds-1.2.5.jar)
With the following connection string: jdbc:jtds:sybase://host:port;databaseName=dbname;ssl=request
I got Network error IOException: Connection refused
Using Jconnect 4 (jconn4.jar)
with the following connection string:
jdbc:sybase:Tds:host:port/dbname?ENABLE_SSL=true
I got java.sql.SQLException: JZ00L: Login failed. Examine the SQLWarnings chained to this exception for the reason(s)
...
java.sql.SQLException: I/O Error: DB server closed connection.
I checked the Sybase log see the following error:
kernel SSL or Crypto Error Message: 'The SSL handshake failed. Root error: error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol'.
it looks like the Sybase server expects SSL connection but the java client still not using SSL (although connection string property marks ssl=true).
tried searching Sybase documentation with not much luck, neither for this error nor for SSL with JConnect.
Any answer will be much appreciated - i'm flexible with the type of driver and the configuration.
Thanks
After much investigation, I found a solution. 2 actually.
Using trust all certificate JDBC connection string parameter:
if you don't mind to trust all certificates (do this only if you entirely trust the network you're working in, especially not anything going on the public internet), you may add a connection string indicating the SSLSocketFactory creating the connection to trust all certificates. The connection string will look as follows: jdbc:sybase:Tds:host:port/dbname?ENABLE_SSL=true&SSL_TRUST_ALL_CERTS=true
Using the sybase certificate:
the certificate needs to be imported to the java application trust store.
in case you're not working with a designated trust store, it may be imported to the Java default trust store found under $JAVA_HOME\jreX\lib\security\cacerts. The certificate may be imported using keytool as explained here.
Although zuckermanori's answer provides some key details, adding more steps below which are required -
Provide right jdbc jar which supports ssl while creating spark session. I was earlier using jconn3-6.0.0.jar which doesnt support ssl. Later, I used jconnect-16.0_SP02.jar which worked fine.
Example pyspark command to pass the driver jar would be -
pyspark --jars
/path/to/your/jdbc/driver/jar
Provide additional java args as follows in the same command to provide trust store location(which has the certificates) -
--conf spark.driver.extraJavaOptions="-Djavax.net.ssl.trustStore=/path/to/truststore -Djavax.net.ssl.trustStorePassword=your_truststore_password"
3. Use right string to load driver in option. Earlier I was using 'com.sybase.jdbc4.jdbc.SybDriver' which didnt work. Then below worked for me -
.option("driver", "com.sybase.jdbc4.jdbc.SybDriver")
4. Use right connection string to provide additional ssl options as per the driver. E.g. -
.option("url", "jdbc:sybase:Tds:host_name:ssl_port/database_name?ENABLE_SSL=true&SSL_TRUST_ALL_CERTS=true&ssl=request")
Additional options required -
.option("ssl", True).option("sslmode", "require")
To sum it up, this is how your pyspark command should look like(if you are using yarn mode, then truststore should be accessible on all nodes. Below is the example of spark local mode) -
pyspark --jars /path/to/your/jdbc/driver/jar --conf spark.driver.extraJavaOptions="-Djavax.net.ssl.trustStore=/path/to/truststore -Djavax.net.ssl.trustStorePassword=your_truststore_password" --master local
And this is how your jdbc read look like -
spark.read.format("jdbc").option("url", "jdbc:sybase:Tds:host_name:ssl_port/database_name?ENABLE_SSL=true&SSL_TRUST_ALL_CERTS=true&ssl=request").option("driver", "com.sybase.jdbc4.jdbc.SybDriver").option("ssl", True).option("sslmode", "require").option("user", "your_user_name").option("password", "your_password").option("dbtable", "db.dbo.table_name").load().show(5)