0

We are facing issue with connecting to Postgres SQL database with certificate (pk8 and key file) in tomcat using Java web application, however when we try to connect with Java standalone we can able to connect.

Upon checking the Catalina logs we found the error –

org.postgresql.util.PSQLException: FATAL: connection requires a valid client certificate

Below is the connection params used in Java web application (as per documentation), the same works fine when tried with standalone application (Refer screen shot below)

jdbc:postgresql://:/<DB_NAME>?sslmode=require&sslcert=/app/localstorage/UAT_Certs/FA1234.crt&sslkey=/app/localstorage/UAT_Certs/FA1234.pk8&sslpassword=XXXX&user=XXXX

Standalone Successful connection:

java -cp postgresql-9.3-1102-jdbc41.jar:Query.jar com.company.test.Query

URL used to connect to Database is

jdbc:postgresql://example.com:5432/sample?sslmode=require&sslcert=/app/localstorage/FA1234.crt&sslkey=/app/localstorage/FA1234.pk8&sslpassword=test&user=test_name

Output:

Current Time in Database is 12:15:48.738587+01

Below is the code which we use in Tomcat to create Data source by passing the necessary DB information:

public  class SecureTomcatDataSourceImpl extends DataSourceFactory {

    private EncDecJDBCPass encryptor = null;
    public SecureTomcatDataSourceImpl() {
        try {
                encryptor = new EncDecJDBCPass();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public DataSource createDataSource(Properties properties, Context context, boolean XA) throws InvalidKeyException,
            IllegalBlockSizeException, BadPaddingException, SQLException, NoSuchAlgorithmException,
            NoSuchPaddingException, UnrecoverableKeyException, KeyManagementException, CertificateException, FileNotFoundException, KeyStoreException, IOException {

        System.out.println("Inside createDataSource() method. ");
        
        //fetching pfx file  encrypted password from context.xml
        PoolConfiguration poolProperties = SecureTomcatDataSourceImpl.parsePoolProperties(properties);

        //poolProperties.setPassword(pwd);

        poolProperties.setPassword(null);
        poolProperties.setUsername("XXXX");
        String urlVal = poolProperties.getUrl();
        System.out.println("Before Append"+urlVal);
        String appendUrlVal =   "jdbc:postgresql://:/<DB_NAME>?sslmode=require&sslcert=/app/localstorage/UAT_Certs/FA1234.crt&sslkey=/app/localstorage/UAT_Certs/FA1234.pk8&sslpassword=XXXX&user=XXXX"


        System.out.println("AppendUrlVal:::::::::::::::"+appendUrlVal);

        poolProperties.setUrl(appendUrlVal);


        // The rest of the code is copied from Tomcat's DataSourceFactory.
        if (poolProperties.getDataSourceJNDI() != null && poolProperties.getDataSource() == null) {
            performJNDILookup(context, poolProperties);
        }
        org.apache.tomcat.jdbc.pool.DataSource dataSource = XA ? new XADataSource(poolProperties)
                : new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);

        String Name = SecureTomcatDataSourceImpl.getProperties("name").toString();
        String URL = poolProperties.getUrl();
        System.out.println("URL VALUE::::::::"+URL);
        String username = poolProperties.getUsername();
        Logger.getLogger(SecureTomcatDataSourceImpl.class.getName()).log(Level.INFO, "Creating a New Connection Pool for DataSource "+Name+" with URL "+URL+" and the  username "+username);

        dataSource.createPool();

        return dataSource;
    }

}

Code used in Standalone Program:

import java.sql.*;
import java.util.Properties;

public class Query {

    public static void main(String[] args) {

        try {
            
            String url = "jdbc:postgresql://:/<DB_NAME>?sslmode=require&sslcert=/app/localstorage/UAT_Certs/FA1234.crt&sslkey=/app/localstorage/UAT_Certs/FA1234.pk8&sslpassword=XXXX&user=XXXX"
            
            System.out.println("URL used to connect to Database is " + url);
            
            Connection conn = DriverManager.getConnection(url);

            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("select current_time");
            while (rs.next()) {
                System.out.println("Current Time in Database is :::::::::::::::::::::::::" + rs.getString("current_time"));
            }
            conn.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
9
  • could you provide some code to look at? So we can understand better the problem Commented Aug 2, 2021 at 7:38
  • I have edited the question with both the code 1) Used in application - Tomcat which connects to DB using Context.xml by creating Data Source 2) Used in Standlaone application - using plain JDBC. In both these cases I have used postgres jar version 42.2.8 Commented Aug 2, 2021 at 9:54
  • Check if this helps: stackoverflow.com/questions/62179397/… Commented Aug 2, 2021 at 10:51
  • What error shows up in the server's log file? The server and the client log different information, and often one will be more useful than the other. Commented Aug 2, 2021 at 20:51
  • Is the standalone being run from the same machine and as the same user as the apache software is? Commented Aug 2, 2021 at 20:53

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.