【Go】pq: password authentication failed for user "xxx" にハマった話
はじめに
Private IPを持ったCloud SQLに、Cloud Run Jobsから、Direct VPC Egressで接続しようとしていました。
しかし、接続がうまくいきません。
ユーザー名やパスワードはあっているはずなのに、以下のエラーが発生しました。
pq: password authentication failed for user "xxx"
なぜでしょうか?
修正前のコード
以下を参考に、TCPで接続する方法を選択しました。
package cloudsql
import (
"database/sql"
"fmt"
"os"
_ "github.com/lib/pq"
)
func connectTCPSocket() (*sql.DB, error) {
dbURI := fmt.Sprintf("host=%s user=%s password=%s port=%s database=%s",
os.Getenv("INSTANCE_HOST"), os.Getenv("DB_USER"), os.Getenv("DB_PASS"), os.Getenv("DB_PORT"), os.Getenv("DB_NAME"))
dbPool, err := sql.Open("postgres", dbURI)
if err != nil {
return nil, fmt.Errorf("sql.Open: %w", err)
}
// ...
if err := dbPool.Ping(); err != nil {
return nil, err
}
return dbPool, nil
}
原因
DBのパスワードに、バックスラッシュ(\
)を含んでいたことが原因でした。
公式ドキュメントにも、キーバリュー形式の接続文字列では、値中のシングルクォート('
)とバックスラッシュ(\
)を バックスラッシュでエスケープする必要があるとあります
To write an empty value, or a value containing spaces, surround it with single quotes, for example keyword = 'a value'. Single quotes and backslashes within a value must be escaped with a backslash, i.e., ' and \. [1]
また、URI 形式の接続文字列では、スキームやパス、パラメータ部に “特別な意味を持つ記号” を含む場合は パーセントエンコーディング が必要です。
The connection URI needs to be encoded with percent-encoding if it includes symbols with special meaning in any of its parts. [2]
解決
net/url
を使って、URI 形式の接続文字列を使用することにしました。
url.UserPassword
を使用して、ユーザー情報をパーセントエンコードします。
package cloudsql
import (
"database/sql"
"fmt"
"net/url"
"os"
_ "github.com/lib/pq"
)
func connectTCPSocket() (*sql.DB, error) {
u := &url.URL{
Scheme: "postgres",
User: url.UserPassword(os.Getenv("DB_USER"), os.Getenv("DB_PASS")),
Host: fmt.Sprintf("%s:%s", os.Getenv("INSTANCE_HOST"), os.Getenv("DB_PORT")),
Path: os.Getenv("DB_NAME"),
}
dbPool, err := sql.Open("postgres", u.String())
if err != nil {
return nil, fmt.Errorf("sql.Open: %w", err)
}
if err := dbPool.Ping(); err != nil {
return nil, err
}
// ...
return dbPool, nil
}
最後に
実は、今回のエラーに遭遇するのは、2回目でした。
前回遭遇したのは、社会人になりたての頃でした。
当時は、自分だけのDBで作業していたので、DBのパスワードを変更して、根本解決はしませんでした。
しかし今回は、一次情報から問題の原因を見つけて、アウトプットまでしたので、我ながら成長が感じられて、なんだか感慨深いです。
Discussion
元気そうでなにより。
またご飯連れて行って下さい!!
そやな