TLS encrypted PostgreSQL connection not possible - postgresql

I would like to establish a TLS encrypted connection to a PostgreSQL 11 database using Tokio as the framework, Deadpool as the connection pooler and rustls as TLS library.
I developed/modified the following code:
let pool = if let Some(ca_cert) = settings.db_ca_cert {
let mut tls_config = ClientConfig::new();
let cert_file = File::open(&ca_cert)?;
let mut buf = BufReader::new(cert_file);
tls_config.root_store.add_pem_file(&mut buf).map_err(|_| {
anyhow::anyhow!("failed to read database root certificate: {}", ca_cert)
})?;
let tls = MakeRustlsConnect::new(tls_config);
settings.pg.create_pool(tls)?
} else {
settings.pg.create_pool(NoTls)?
};
My test scenario is taken from here:
PostgreSQL 11 docker container (including TLS turned on)
TLS was already tested successfully with the psql client
I now get the following error message and can't explain the problem. I already checked the access rights and other parameters.
/usr/local/bin/cargo run --color=always
Finished dev [unoptimized + debuginfo] target(s) in 0.20s
Running `target/debug/tokio-postgres-rustls-connection-pool-demo`
DEBUG tokio_postgres_rustls_connection_pool_demo > settings: Settings { pg: Config { user: Some("postgres"), password: Some("postgres"), dbname: Some("postgres"), options: Some("sslrootcert=/xxx/tokio-postgres-rustls-connection-pool-demo/docker/files/cert/ca.pem"), application_name: None, ssl_mode: None, host: Some("127.0.0.1"), hosts: None, port: Some(6432), ports: None, connect_timeout: None, keepalives: None, keepalives_idle: None, target_session_attrs: None, channel_binding: None, manager: None, pool: None }, db_ca_cert: None }
Error: Backend(Error { kind: Connect, cause: Some(Os { code: 2, kind: NotFound, message: "No such file or directory" }) })
I looked at the logs of the database and could identify the following error:
[86] LOG: XX000: could not accept SSL connection: Success
[86] LOCATION: be_tls_open_server, be-secure-openssl.c:408
How can I solve the problem?

Related

ContainerApp Revision Failed when using dapr

I have created containerapp environment with one containerapp using Bicep template and here is a snippet of how I configured the environment
ingress: {
external: true
targetPort: 80
allowInsecure: false
transport:'http2'
traffic:[
{
latestRevision: true
weight: 100
}
]
}
registries: [
{
server: acr_login_server
username: acr_name
passwordSecretRef: 'myregistrypassword'
}
]
dapr: {
appId: containerapp_name
appPort: 80
appProtocol: 'http'
enabled: true
}
}
I am using http2 transport cause we expose grpc service as well, then when checking the revision, it shows failed and the logs shows that there is issue with dapr
time="2022-10-19T10:35:35.391746798Z" level=fatal msg="error loading configuration: rpc error: code = Unavailable desc = connection error: desc = \"transport: authentication handshake failed: x509: certificate signed by unknown authority (possibly because of \\\"x509: ECDSA verification failure\\\" while trying to verify candidate authority certificate \\\"cluster.local\\\")\"" app_id=containerapp-a instance=containerapp-a--t1gheb2-77c44cf6c6-rxjwx scope=dapr.runtime type=log ver=1.8.4-msft-2

Unable to put Vapor project with Postgres database on a VPS

I'm a newbie with database and Vapor. I'm trying to put a vapor project on a Postgres database on a VPS but I had this error:
2022-08-05 11:18:26.611154+0200 Run[16315:261688] Swift/ErrorType.swift:200: Fatal error: Error raised at top level: PostgresNIO.PSQLError(base: PostgresNIO.PSQLError.Base.connectionError(underlying: NIOPosix.NIOConnectionError(host: "82.125.176.210", port: 5432, dnsAError: nil, dnsAAAAError: nil, connectionErrors: [NIOPosix.SingleConnectionFailure(target: [IPv4]82.125.176.210/82.125.176.210:5432, error: connection reset (error set): Operation timed out (errno: 60))])))
Here my code:
import Fluent
import FluentPostgresDriver
import Vapor
import Leaf
public func configure(_ app: Application) throws {
app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))
app.middleware.use(app.sessions.middleware)
let databaseName: String
let databasePort: Int
databaseName = "vapor_database"
databasePort = 5432
app.databases.use(.postgres(
hostname: "82.125.176.210",
port: databasePort,
username: Environment.get("DATABASE_USERNAME") ?? "456787555",
password: Environment.get("DATABASE_PASSWORD") ?? "456787555",
database: Environment.get("DATABASE_NAME") ?? databaseName
), as: .psql)
app.migrations.add(CreateUser())
app.migrations.add(CreateAcronym())
app.migrations.add(CreateCategory())
app.migrations.add(CreateAcronymCategoryPivot())
app.migrations.add(CreateToken())
switch app.environment {
case .development, .testing:
app.migrations.add(CreateAdminUser())
default:
break
}
app.migrations.add(AddTwitterURLToUser())
app.migrations.add(MakeCategoriesUnique())
app.logger.logLevel = .debug
try app.autoMigrate().wait()
app.views.use(.leaf)
// register routes
try routes(app)
}
A timeout error usually means that there's no route to the database server because it's being blocked by a firewall. (As opposed to a connection refused error if there's nothing listening on that port). Make sure you set a rule in the firewall to allow the Vapor app to connect

How can I help Vapor successfully SSL-handshake my PostgreSQL server?

I'm using Vapor on a Ubuntu server to connect to my DigitalOcean-managed PostgreSQL database.
From the command-line, running the following works fine:
psql postgresql://user:password#host:port/dbname?sslmode=require
But running the equivalent with the following code gives me:
Fatal error: Error raised at top level: NIOOpenSSL.NIOOpenSSLError.handshakeFailed(NIOOpenSSL.OpenSSLError.sslError([Error: 337047686 error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed])): file /home/buildnode/jenkins/workspace/oss-swift-5.1-package-linux-ubuntu-18_04/swift/stdlib/public/core/ErrorType.swift, line 200
Here is the code:
let postgres = PostgreSQLDatabase(config: PostgreSQLDatabaseConfig(
hostname: Environment.get("POSTGRESQL_HOSTNAME")!,
port: Int(Environment.get("POSTGRESQL_PORT")!)!,
username: Environment.get("POSTGRESQL_USERNAME")!,
database: Environment.get("POSTGRESQL_DATABASE")!,
password: Environment.get("POSTGRESQL_PASSWORD")!,
transport: .standardTLS
))
Switching the transport argument to .unverifiedTLS works.
I need help to let Vapor work out the SSL connection fine, but I have no idea where to start.
I recently got this working with Vapor 4 and MySQL on Digital Ocean, I suspect the same will work for PostgreSQL. The main bit was configuring Vapor to trust Digital Ocean's certificate.
Download the CA certificate from the managed database dashboard on Digital Ocean (the connection details section).
Configure the database tlsConfigurataion to trust that certificate. Here's an example of what that could look like:
import NIOSSL
public func configure(_ app: Application) throws {
app.databases.use(.postgres(
hostname: Environment.get("DATABASE_HOST") ?? "localhost",
port: Environment.get("DATABASE_PORT").flatMap(Int.init(_:)) ?? PostgresConfiguration.ianaPortNumber,
username: Environment.get("DATABASE_USERNAME") ?? "vapor_username",
password: Environment.get("DATABASE_PASSWORD") ?? "vapor_password",
database: Environment.get("DATABASE_NAME") ?? "vapor_database",
tlsConfiguration: try makeTlsConfiguration()
), as: .psql)
// ...
}
private func makeTlsConfiguration() throws -> TLSConfiguration {
var tlsConfiguration = TLSConfiguration.makeClientConfiguration()
if let certPath = Environment.get("DATABASE_SSL_CERT_PATH") {
tlsConfiguration.trustRoots = NIOSSLTrustRoots.certificates(
try NIOSSLCertificate.fromPEMFile(certPath)
)
}
return tlsConfiguration
}
In this example, I use the DATABASE_SSL_CERT_PATH environment variable to set the path of the downloaded ca-certificate.crt file.

issues connecting to postgres using pg client

Trying to connect to postgres using the pg client (following these instructions).
Here is my connection string var connectionString = "postgres://postgres:pass#localhost/ip:5432/chat";
Here's the error I'm getting trying to connect:
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): error: database "ip:5432/twitchchat" does not exist
However, when I run pg_isready I get the response /tmp:5432 - accepting connections Which I read as telling me postgres is running on port 5432.
The database is very definitely existing.
Here's the simple connection code:
var pg = require('pg');
var connectionString =
"postgres://postgres:pass#localhost/ip:5432/chat";
var connection = new pg.Client(connectionString);
connection.connect();
What's happening here? How do I fix this?
Your connection string is malformed:
Change it to:
`"postgres://postgres:pass#localhost:5432/chat"`
The correct format is:
postgresql://[user]:[password]#[address]:[port]/[dbname]
Ok I fixed it with the following:
const { Client } = require('pg');
const connection = new Client({
user: 'postgres',
host: 'localhost',
database: 'chat',
password: 'pass',
port: 5432,
});
connection.connect();

Connecting to postgresql from lapis

I decided to play with lapis - https://github.com/leafo/lapis, but the application drops when I try to query the database (PostgreSQL) with the output:
2017/07/01 16:04:26 [error] 31284#0: *8 lua entry thread aborted: runtime error: attempt to yield across C-call boundary
stack traceback:
coroutine 0:
[C]: in function 'require'
/usr/local/share/lua/5.1/lapis/init.lua:15: in function 'serve'
content_by_lua(nginx.conf.compiled:22):2: in function , client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "localhost:8080"
The code that causes the error:
local db = require("lapis.db")
local res = db.query("SELECT * FROM users");
config.lua:
config({ "development", "production" }, {
postgres = {
host = "0.0.0.0",
port = "5432",
user = "wars_base",
password = "12345",
database = "wars_base"
}
})
The database is running, the table is created, in table 1 there is a record.
What could be the problem?
Decision: https://github.com/leafo/lapis/issues/556
You need to specify the right server IP in the host parameter.
The IP you have specified 0.0.0.0 is not a valid one, and normally it is used when you specify a listen address, with the meaning of "every address".
Usually you can use the '127.0.0.1' address during development.