✍️

Go で SSH 超しに PostgreSQL に接続できる database/sql ドライバを作った。

2021/08/16に公開

はじめに

データベースを扱う際に、データベースサーバがローカルネットワーク内に存在すれば直接接続できるのですが、時にはデータベースサーバが遠隔にあり ssh を介してしか接続できないケースもあります。そういった場合、ポートフォワーディング等を使って接続するなどしないといけません。

しかしながら、その為には事前に ssh コマンドでトンネルを掘る必要があり、バッチ的に遠隔のデータベースを操作するのは幾分手間が掛かります。

SSH を超えてデータベースに接続する

database/sql にはドライバを自分で作る機能があります。そしてデータベースに接続する際のコネクタを自作する事ができる様になっています。crypto/ssh でサーバにログインし、その先で Dial を実行する事で、あたかもローカルのデータベースに接続しているかの様なコネクションを PostgreSQL のコネクションとして渡す事ができます。

実装

実装はとてもシンプルです。以前 Go で実装した ssh コマンドから幾らかソースを持ってきました。

https://github.com/mattn/pqssh

現在サポートしている認証方法は

  • パスワード認証
  • ssh-agent を介した公開鍵認証
  • パスフレーズを使った公開鍵認証

になります。現在は RSA 鍵しかサポートしていません。

使い方

通常の database/sql ドライバの場合は、ドライバを import すると自動でドライバが登録されますが、本ドライバの場合はご自分で登録して頂く必要があります。

driver := &pqssh.Driver{
	Hostname:   "my-server",
	Port:       22,
	Username:   "sshuser",
	Password:   "sshpassword",
	PrivateKey: "/home/mattn/.ssh/id_rsa",
}

sql.Register("postgres+ssh", driver)

この struct フィールに登録された情報を使って ssh サーバにログインします。あとはこの postgres+ssh (実際何でもいい) を使って接続するだけです。

db, err := sql.Open("postgres+ssh", "postgres://my-db-user:my-db-password@127.0.0.1:5432/example?sslmode=disable")

これでデータベースに接続できれば、あとは ssh を介している事を特に気にする必要はありません。使い方は README を参照するとだいたい分かると思います。

おわりに

ssh 超しに PostgreSQL を扱える Go のドライバ pqssh を作りました。まだテストもないレベルですが、ひとまず自分の PC から VPS 上で動いている PostgreSQL サーバの操作ができています。もし興味があれば使ってみて下さい。

Discussion