PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Configure um `DataSource` para se conectar a um servidor Postgres gerenciado no Digital Ocean com criptografia SSL/TLS

Obtendo uma DataSource implementação


Normalmente, seu driver JDBC fornece uma implementação de javax.sql.DataSource .

Para obter mais detalhes, consulte minha resposta para uma pergunta semelhante.

PGSimpleDataSource


Se estiver usando o driver JDBC de jdbc.postgresql.org , você pode usar o org.postgresql.ds.PGSimpleDataSource class como seu DataSource implementação.

Instanciar um objeto do tipo PGSimpleDataSource , chame os métodos setter para fornecer todas as informações necessárias para se conectar ao servidor de banco de dados. A página da Web no site da DigitalOcean lista todas essas informações para sua instância de banco de dados específica.

Basicamente isso:
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" );

Nomes de servidor e números de porta no plural


Infelizmente, a versão singular dos métodos setServerName e setPortNumber são preteridos. Embora irritante, provavelmente devemos usar a versão plural desses métodos (setServerNames &setPortNumbers ) que cada um recebe uma matriz. Preenchemos um par de arrays de elemento único, String[] e int[] , com o endereço do nosso servidor e número da porta usando literais de matriz:
  • { "seu-servidor-endereço-vai-aqui" }
  • { your-port-number-goes-here }
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" );

Criptografia SSL/TLS


Por fim, precisamos adicionar informações para a criptografia SSL/TLS abordada na pergunta.

Ironicamente, não chame setSsl( true )


Você pensaria que chamaríamos o setSsl e passe true . Mas não. Embora seja contra-intuitivo, definir isso como verdadeiro fará com que suas tentativas de conexão falhem. Eu não sei por que isso é. Mas tentativa e erro me levaram a evitar essa ligação.

Certificado de CA


Para que seu aplicativo Java do lado do cliente inicie a conexão SSL/TLS, o driver JDBC deve ter acesso ao certificado CA usado pela Digital Ocean. Na página de administração do Digital Ocean, clique em Download CA certificate link para baixar um pequeno arquivo de texto. Esse arquivo será nomeado ca-certificate.crt .

Precisamos alimentar o texto desse arquivo para nosso driver JDBC como uma string. Faça o seguinte para carregar o arquivo em uma string 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." ); }

Passe o texto do certificado de CA para o driver JDBC com uma chamada para DataSource::setSslCert . Observe que não chamando setSslRootCert . Não misture os dois métodos com nomes semelhantes.
dataSource.setSslCert( cert );

Testando a conexão


Por fim, podemos usar o DataSource configurado objeto para fazer uma conexão com o banco de dados. Esse código ficará assim:
// Test connection
try (
        Connection conn = dataSource.getConnection() ;
        // …
)
{
    System.out.println( "DEBUG - Postgres connection made. " + Instant.now() );
    // …
}
catch ( SQLException e )
{
    e.printStackTrace();
}

Código de exemplo completo


Juntando tudo isso, veja algo assim.
// 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();
}

Fonte confiável


Ao criar sua instância do Postgres no DigitalOcean.com, você terá a capacidade de restringir as solicitações de conexão recebidas. Você pode especificar um único endereço IP a ser esperado pelo servidor Postgres, uma “fonte confiável” no jargão da Digital Ocean. Quaisquer hackers que tentem se conectar ao seu servidor Postgres serão ignorados, pois são originários de outros endereços IP.

Dica:Clique dentro do campo de entrada de dados para este número de endereço IP para que a página da web detecte automaticamente e ofereça o endereço IP que está sendo usado atualmente pelo seu navegador da web. Se você estiver executando seu código Java no mesmo computador, use esse mesmo número IP como sua única fonte confiável.

Caso contrário, digite o endereço IP do computador que está executando seu código Java JDBC.

Outros problemas


Não abordei elaborações, como protocolos de segurança adequados para usar para gerenciar seu arquivo de certificado de CA ou como externalizar suas informações de conexão obtendo um DataSource objeto de um JNDI servidor em vez de hard-coding . Mas espero que os exemplos acima ajudem você a começar.