Error: failed to connect to database: password authentication failed in Rust - postgresql

I am trying to connect to database in Rust using sqlx crate and Postgres database.
main.rs:
use dotenv;
use sqlx::Pool;
use sqlx::PgPool;
use sqlx::query;
#[async_std::main]
async fn main() -> Result<(), Error> {
dotenv::dotenv().ok();
pretty_env_logger::init();
let url = std::env::var("DATABASE_URL").unwrap();
dbg!(url);
let db_url = std::env::var("DATABASE_URL")?;
let db_pool: PgPool = Pool::new(&db_url).await?;
let rows = query!("select 1 as one").fetch_one(&db_pool).await?;
dbg!(rows);
let mut app = tide::new();
app.at("/").get(|_| async move {Ok("Hello Rustacean!")});
app.listen("127.0.0.1:8080").await?;
Ok(())
}
#[derive(thiserror::Error, Debug)]
enum Error {
#[error(transparent)]
DbError(#[from] sqlx::Error),
#[error(transparent)]
IoError(#[from] std::io::Error),
#[error(transparent)]
VarError(#[from] std::env::VarError),
}
Here is my .env file:
DATABASE_URL=postgres://localhost/twitter
RUST_LOG=trace
Error log:
error: failed to connect to database: password authentication failed for user "ayman"
--> src/main.rs:19:16
|
19 | let rows = query!("select 1 as one").fetch_one(&db_pool).await?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
error: could not compile `backend`.
Note:
There exists a database called twitter.
I have include macros for sqlx's dependency
sqlx = {version="0.3.5", features = ["runtime-async-std", "macros", "chrono", "json", "postgres", "uuid"]}
Am I missing some level of authentication for connecting to database? I could not find it in docs for sqlx::Query macro

The reason why it is unable to authenticate is that you must provide credentials before accessing the database
There are two ways to do it
Option 1: Change your URL to contain the credentials - For instance -
DATABASE_URL=postgres://localhost?dbname=mydb&user=postgres&password=postgres
Option 2 Use PgConnectionOptions - For instance
let pool_options = PgConnectOptions::new()
.host("localhost")
.port(5432)
.username("dbuser")
.database("dbtest")
.password("dbpassword");
let pool: PgPool = Pool::<Postgres>::connect_with(pool_options).await?;
Note: The sqlx version that I am using is sqlx = {version="0.5.1"}
For more information refer the docs - https://docs.rs/sqlx/0.5.1/sqlx/postgres/struct.PgConnectOptions.html#method.password
Hope this helps you.

Related

Wasm-rust and postgres

is there a way to get data from a database in postgres using wasm?. I'd tried to get it using a library in rust but I got some errore when I build the package using "wasm-pack building--target web". The idea is to build a function in lib.rs file that return data from a db. I have the below code inside lib.rs:
use postgres::{Client, Error, NoTls};
use wasm_bindgen::prelude::*;
...
struct Author {
_id: i32,
name: String,
}
#[wasm_bindgen]
pub fn select_name(name: &String) -> Result<(), Error> {
let mut client = Client::connect("postgresql://user:1234#localhost:5432/db", NoTls)?;
for row in client.query(
"SELECT id, name FROM author WHERE name = $1",
&[&name],
)? {
let author = Author {
_id: row.get(0),
name: row.get(1),
};
println!(
"Select_Name => Author {} :",
author.name
);
}
Ok(())
}
but I get some errors:
error[E0432]: unresolved import `crate::sys::IoSourceState`
error[E0432]: unresolved import `crate::sys`
...
It is not possible directly (as Njuguna Mureithi rightly wrote) but it can be circumvented.
We can use the project: https://github.com/PostgREST/postgrest
and expose the API to our sql server.
We download the latest version of postgrest
https://github.com/PostgREST/postgrest/releases/tag/v9.0.0
in case of Linux we unpack
tar -xf postgrest-v9.0.0-linux-static-x64.tar.xz
then run help
./postgrest -h
create a configuration file for ./postgrest
postgrest -e > cfg.psqlrest
change the user and password for the database in the configuration file.
e.g. with
db-uri = "postgres://user:pasword#localhost:5432/dbname"
to your dbname database access user:pasword configuration
db-uri = "postgres://postgres:zaqwsxc#localhost:5432/dbname"
and run the server which will issue the api to our postgres
./postgrest cfg.psqlrest
The address http://localhost:3000 will start accessing the database dbname, which must be created in the database server beforehand.
Here is a description of the libraries needed to call the query using the API.
https://rustwasm.github.io/wasm-bindgen/examples/fetch.html
examples of API
https://postgrest.org/en/stable/api.html

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.

Unable to connect to MongoDB when using a URI with credentials

I'm trying to build a simple CRUD API with the MongoDB Rust driver but I'm failing to insert anything into the DB. I'm using Mlab to host my database.
The code that I'm running:
#[macro_use(bson, doc)]
extern crate bson;
extern crate mongodb;
use mongodb::db::ThreadedDatabase;
use mongodb::{Client, ThreadedClient};
fn main() {
let client = Client::with_uri(
"mongodb://<my_db_username>:<my_db_password>#ds235711.mlab.com:35711/rustcrud",
)
.expect("Failed to initialize client");
let coll = client.db("rustcrud").collection("test");
coll.insert_one(doc! { "title": "Back to the Future" }, None)
.unwrap();
}
And the error that I get:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: OperationError("not authorized on rustcrud to execute command { insert: \"test\", $db: \"rustcrud\" }")', libcore/result.rs:1009:5
What am I doing wrong?
From the project's GitHub repository, issue 256: Add auth to base examples
user-password authentication occurs at the database-level. The user, password, and database are parsed from the URI, but I don't believe we have it set up to automatically authenticate when you create the database object
let client = Client::with_uri("mongodb://x:y#localhost:27017")?;
client.auth("x", "y");

Configure PostgreSQL DB with Vapor 3 on Heroku

I've built a simple Vapor 3 API that I'd like to deploy on Heroku. I'd like it to be backed by a PostgreSQL database which is also attached to another Heroku app (I have successfully attached the DB in the Heroku dashboard – and the DB works correctly in the other application). However, my Vapor app never completes starting up, crashing with the following error:
Fatal error: Error raised at top level: ⚠️ PostgreSQL Error: no pg_hba.conf entry for host "[the IP addr]", user "[heroku postgres username here]", database "[heroku psql db here]", SSL off
- id: PostgreSQLError.server.fatal.ClientAuthentication
I used vapor heroku init to set up the Heroku app. I've Googled around, and tried adding a Procfile and messing with configure.swift, but so far no luck. Here are all the relevant files I can think of:
Procfile:
web: Run serve --env production --hostname 0.0.0.0 --port $PORT --config:postgresql.url $DATABASE_URL
configure.swift:
import FluentPostgreSQL
import Vapor
/// Called before your application initializes.
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
/// Register providers first
try services.register(FluentPostgreSQLProvider())
var contentConfig = ContentConfig.default()
/// Create custom JSON encoder
let jsonEncoder = JSONEncoder()
if #available(OSX 10.12, *) {
jsonEncoder.dateEncodingStrategy = .iso8601
} else {
jsonEncoder.dateEncodingStrategy = .millisecondsSince1970
}
// jsonEncoder.keyEncodingStrategy = .convertToSnakeCase
/// Register JSON encoder and content config
contentConfig.use(encoder: jsonEncoder, for: .json)
services.register(contentConfig)
/// Register routes to the router
let router = EngineRouter.default()
try routes(router)
services.register(router, as: Router.self)
/// Register middleware
var middlewares = MiddlewareConfig() // Create _empty_ middleware config
/// middlewares.use(FileMiddleware.self) // Serves files from `Public/` directory
middlewares.use(ErrorMiddleware.self) // Catches errors and converts to HTTP response
services.register(middlewares)
// Configure a database
let dbConfig: PostgreSQLDatabaseConfig
if let url = Environment.get("DATABASE_URL"), let psqlConfig = PostgreSQLDatabaseConfig(url: url) {
dbConfig = psqlConfig
} else {
dbConfig = PostgreSQLDatabaseConfig(hostname: "localhost", port: 5432, username: "admin", database: "development", password: nil)
}
let postgresql = try PostgreSQLDatabase(config: dbConfig)
/// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.add(database: postgresql, as: .psql)
services.register(databases)
/// Configure migrations
var migrations = MigrationConfig()
migrations.add(model: Visit.self, database: .psql)
services.register(migrations)
}
Package.swift:
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "SubwayNyc",
dependencies: [
// 💧 A server-side Swift web framework.
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),
// 🔵 Swift ORM (queries, models, relations, etc) built on PostgreSQL.
.package(url: "https://github.com/vapor/fluent-postgresql.git", from: "1.0.0"),
.package(url: "https://github.com/vapor/sql.git", from: "2.1.0")
],
targets: [
.target(name: "App", dependencies: ["FluentPostgreSQL", "Vapor"]),
.target(name: "Run", dependencies: ["App"]),
.testTarget(name: "AppTests", dependencies: ["App"])
]
)
How can I get PostgreSQL hooked up to my Vapor 3 app on Heroku?
For Heroku we need unverifiedTLS transport.
https://api.vapor.codes/postgresql/latest/PostgreSQL/Classes/PostgreSQLConnection/TransportConfig.html
let pgURL = Environment.get("DATABASE_URL") ?? "postgres://user:password#host:port/database"
let pgConfig = PostgreSQLDatabaseConfig(url: pgURL, transport: PostgreSQLConnection.TransportConfig.unverifiedTLS)!
:D
The original error is the key here, in particular: SSL off.
This error is thrown by Heroku Postgres when the client is attempting to connect without SSL. Not familiar with Vapor myself, but a quick look around suggests that configure.swift is where you can make configuration changes. Once you enable SSL from the client, you should be able to connect to this database instance without issue.

Xcode error when building Vapor 3 framework

I had this error when trying to build from XCode , albeit it builds from terminal
clang: error: no such file or directory: '/Users/++/Desktop/vapor/til/.build/checkouts/sqlite.git--8232814251736334455/Sources/CSQLite/sqlite3.c'
clang: error: no input files
I'm using pgsql and this is my configure.swift
// 1
import FluentPostgreSQL
import Vapor
public func configure(
_ config: inout Config,
_ env: inout Environment,
_ services: inout Services
) throws {
// 2
try services.register(FluentPostgreSQLProvider())
let router = EngineRouter.default()
try routes(router)
services.register(router, as: Router.self)
var middlewares = MiddlewareConfig()
middlewares.use(ErrorMiddleware.self)
services.register(middlewares)
// 1
var databases = DatabasesConfig()
// 2
let hostname = Environment.get("DATABASE_HOSTNAME")
?? "localhost"
let username = Environment.get("DATABASE_USER") ?? "vapor"
let databaseName = Environment.get("DATABASE_DB") ?? "vapor"
let password = Environment.get("DATABASE_PASSWORD")
?? "password"
// 3
let databaseConfig = PostgreSQLDatabaseConfig(
hostname: hname,
username: username,
database: databasesName,
password: password)
// 4
let database = PostgreSQLDatabase(config: databaseConfig)
// 5
databases.add(database: database, as: .psql)
// 6
services.register(databases)
var migrations = MigrationConfig()
// 4
migrations.add(model: Acronym.self, database: .psql)
services.register(migrations)
}
I removed XCode and reinstalled it but no effect
After making sure that you removed any traces of the fluent-sqlite package from your Package.swift file (since your code suggests using PostgreSQL now), please try deleting your .build folder, along with a few regeneratable items with the following commands:
rm -rf .build
rm -rf til.xcodeproj # or however is your Xcode project file called
rm Package.resolved
Then you can re-generate your Xcode project with vapor xcode and/or you can try building from command line again.