LoginSignup
0
0

More than 1 year has passed since last update.

RustでHeroku Postgresに接続する方法

Last updated at Posted at 2022-04-25

環境

Cargo.toml
tokio = { version = "1.17.0", features = ["full"] }
tokio-postgres = "0.7.5"
openssl = "0.10.38"
postgres-openssl = "0.5.0"

問題

tokio-postgresのDocumentを参考にプログラムを書くと、とりあえず以下のようになる。

use dotenv::dotenv;
use std::env;

async fn connect_to_database() -> Result<tokio_postgres::Client, Box<dyn std::error::Error>> {
    dotenv().ok();
    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let (client, connection) = tokio_postgres::connect(&database_url, tokio_postgres::NoTls).await?;
    tokio::spawn(async move {
        if let Err(e) = connection.await {
            eprintln!("connection error: {}", e);
        }
    });
    Ok(client)
}

(ここではdotenvについては触れない)

ローカル環境のデータベースにならこれでも接続できるが、Herokuにデプロイして実行してみると以下のようなエラーが発生する。

Error: Error { kind: Tls, cause: Some(NoTlsError(())) }

どうやら、SSL/TLSの設定をしなければならないようだ。
おそらくtokio_postgres::connectの第2引数に指定すればいいのだが、一体何を指定すればいいのだろうか。

解決

いろいろ調べた結果、最終的に接続に成功することができた。

手順

  1. opensslpostgres-opensslを追加する
  2. Heroku上で実行する際にSSL証明書を作成するようにする
  3. 以下のコードで接続ができる
use dotenv::dotenv;
use std::env;
use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode};
use postgres_openssl::MakeTlsConnector;


async fn connect_to_database() -> Result<tokio_postgres::Client, Box<dyn std::error::Error>> {
    dotenv().ok();
    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let mut builder =
        SslConnector::builder(SslMethod::tls()).expect("unable to create sslconnector builder");
    builder
        .set_ca_file("tmp/ca.crt")
        .expect("unable to load ca.cert");
    builder.set_verify(SslVerifyMode::NONE);
    let connector = MakeTlsConnector::new(builder.build());
    let (client, connection) = tokio_postgres::connect(&database_url, connector).await?;
    tokio::spawn(async move {
        if let Err(e) = connection.await {
            eprintln!("connection error: {}", e);
        }
    });
    Ok(client)
}

SSL証明書の作成は以下のコマンドで行なった。

openssl genrsa -out ./tmp/ca.key 2048 && openssl req -new -key ./tmp/ca.key -out ./tmp/ca.csr -subj '/C=JP/ST=Tokyo/L=Shibuya-ku/O=Oreore CA inc./OU=Oreore Gr./CN=Oreore CA' && openssl x509 -days 3650 -in ./tmp/ca.csr -req -signkey ./tmp/ca.key -out ./tmp/ca.crt

(このコマンドはHeroku上で行う)

参考

おわりに

Rust、SSLの知識が何もない状態で見様見真似でやったのでもっと良い方法がきっとある。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0