sql >> Base de Datos >  >> RDS >> PostgreSQL

Configure un `DataSource` para conectarse a un servidor Postgres administrado en Digital Ocean con cifrado SSL/TLS

Obtención de una DataSource implementación

Por lo general, su controlador JDBC proporciona una implementación de javax.sql.DataSource .

Para obtener más detalles, consulte mi respuesta a una pregunta similar.

PGSimpleDataSource

Si usa el controlador JDBC de jdbc.postgresql.org , puede usar el org.postgresql.ds.PGSimpleDataSource clase como su DataSource implementación.

Crea una instancia de un objeto de tipo PGSimpleDataSource , luego llame a los métodos de establecimiento para proporcionar toda la información necesaria para conectarse a su servidor de base de datos. La página web en el sitio de DigitalOcean enumera toda esta información para su instancia de base de datos en particular.

Básicamente esto:

PGSimpleDataSource dataSource = new PGSimpleDataSource();

dataSource.setServerName( "your-server-address-goes-here" );
dataSource.setPortNumber( your-port-number-goes-here );
dataSource.setDatabaseName( "defaultdb" );
dataSource.setUser( "doadmin" );
dataSource.setPassword( "your-password-goes-here" );

Nombres de servidor y números de puerto en plural

Desafortunadamente, la versión singular de los métodos setServerName y setPortNumber están en desuso. Si bien es molesto, probablemente deberíamos usar la versión plural de esos métodos (setServerNames &setPortNumbers ) que cada uno toma una matriz. Rellenamos un par de matrices de un solo elemento, String[] y int[] , con la dirección de nuestro servidor y número de puerto usando arreglos literales:

  • { "la-dirección-de-su-servidor-va-aquí" }
  • { su-número-de-puerto-va-aquí }
PGSimpleDataSource dataSource = new PGSimpleDataSource();

String[] serverAddresses = { "your-server-address-goes-here" };
dataSource.setServerNames( serverAddresses );
int[] serverPortNumbers = { your-port-number-goes-here };
dataSource.setPortNumbers( serverPortNumbers );
dataSource.setDatabaseName( "defaultdb" );
dataSource.setUser( "doadmin" );
dataSource.setPassword( "your-password-goes-here" );

Cifrado SSL/TLS

Por último, debemos agregar información para el cifrado SSL/TLS abordado en la pregunta.

Irónicamente, no llamar a setSsl( true )

Se podría pensar que llamaríamos al setSsl método y pase true . Pero no. Si bien es contrario a la intuición, establecerlo en verdadero hará que sus intentos de conexión fallen. No sé por qué es eso. Pero la prueba y el error me llevaron a evitar esa llamada.

Certificado CA

Para que su aplicación Java del lado del cliente inicie la conexión SSL/TLS, el controlador JDBC debe tener acceso al certificado CA utilizado por Digital Ocean. En su página de administración de Digital Ocean, haga clic en Download CA certificate enlace para descargar un pequeño archivo de texto. Ese archivo se llamará ca-certificate.crt .

Necesitamos enviar el texto de ese archivo a nuestro controlador JDBC como una cadena. Haga lo siguiente para cargar el archivo en una cadena de texto.

// Get CA certificate used in TLS connections.
Path path = Paths.get( "/Users/basilbourque/Downloads/ca-certificate.crt" );
String cert = null;
try
{
    cert = Files.readString( path , StandardCharsets.UTF_8 );
    System.out.println( "cert = " + cert );
}
catch ( IOException ex )
{
    throw new IllegalStateException( "Unable to load the TLS certificate needed to make database connections." );
}
Objects.requireNonNull( cert );
if ( cert.isEmpty() ) {throw new IllegalStateException( "Failed to load TLS cert." ); }

Pase ese texto de certificado de CA a su controlador JDBC con una llamada a DataSource::setSslCert . Tenga en cuenta que no llamando a setSslRootCert . No mezcle los dos métodos con nombres similares.

dataSource.setSslCert( cert );

Probando la conexión

Por último, podemos usar el DataSource configurado objeto para establecer una conexión con la base de datos. Ese código se verá así:

// Test connection
try (
        Connection conn = dataSource.getConnection() ;
        // …
)
{
    System.out.println( "DEBUG - Postgres connection made. " + Instant.now() );
    // …
}
catch ( SQLException e )
{
    e.printStackTrace();
}

Código de ejemplo completo

Poniendo todo eso junto, vea algo como esto.

// Get CA certificate used in TLS connections.
Path path = Paths.get( "/Users/basilbourque/Downloads/ca-certificate.crt" );
String cert = null;
try
{
    cert = Files.readString( path , StandardCharsets.UTF_8 );
    System.out.println( "cert = " + cert );
}
catch ( IOException ex )
{
    throw new IllegalStateException( "Unable to load the TLS certificate needed to make database connections." );
}
Objects.requireNonNull( cert );
if ( cert.isEmpty() ) {throw new IllegalStateException( "Failed to load TLS cert." ); }

// PGSimpleDataSource configuration
PGSimpleDataSource dataSource = new PGSimpleDataSource();

String[] serverAddresses = { "your-server-address-goes-here" };
dataSource.setServerNames( serverAddresses );
int[] serverPortNumbers = { your-port-number-goes-here };
dataSource.setPortNumbers( serverPortNumbers );
dataSource.setSslCert( cert );
dataSource.setDatabaseName( "defaultdb" );
dataSource.setUser( "doadmin" );
dataSource.setPassword( "your-password-goes-here" );

// Test connection
try (
Connection conn = dataSource.getConnection() ;
// …
)
{
System.out.println( "DEBUG - Postgres connection made. " + Instant.now() );
// …
}
catch ( SQLException e )
{
e.printStackTrace();
}

Fuente confiable

Al crear su instancia de Postgres en DigitalOcean.com, se le ofrecerá la posibilidad de restringir las solicitudes de conexión entrantes. Puede especificar una sola dirección IP que esperará el servidor de Postgres, una "fuente confiable" en la jerga de Digital Ocean. Cualquier pirata informático que intente conectarse a su servidor de Postgres será ignorado ya que se origina en otras direcciones IP.

Sugerencia:haga clic dentro del campo de entrada de datos para este número de dirección IP para que la página web detecte automáticamente y ofrezca la dirección IP que su navegador web está utilizando actualmente. Si está ejecutando su código Java desde la misma computadora, use ese mismo número de IP como su única fuente confiable.

De lo contrario, escriba la dirección IP de la computadora que ejecuta su código Java JDBC.

Otros problemas

No he abordado las elaboraciones, como los protocolos de seguridad adecuados para usar para administrar su archivo de certificado de CA, o como externalizar su información de conexión obteniendo un DataSource objeto desde un JNDI servidor en lugar de hard-coding . Pero espero que los ejemplos anteriores te ayuden a empezar.