From 1ba8735af1278912e7e205cd6e76df7622a28af5 Mon Sep 17 00:00:00 2001 From: Garet Halliday <me@garet.holiday> Date: Tue, 8 Aug 2023 18:31:48 -0600 Subject: [PATCH] auth_file for plaintext passwords --- lib/bouncer/backends/v0/accept.go | 2 +- lib/gat/configs/pgbouncer/config.go | 51 +++++++++++++++---- lib/gat/pool.go | 38 +++++++------- lib/util/{ => encoding}/ini/readfile.go | 0 lib/util/{ => encoding}/ini/unmarshal.go | 0 lib/util/{ => encoding}/ini/unmarshal_test.go | 0 lib/util/encoding/userlist/unmarshal.go | 42 +++++++++++++++ pgbouncer.ini | 10 ++++ userlist.txt | 1 + 9 files changed, 116 insertions(+), 28 deletions(-) rename lib/util/{ => encoding}/ini/readfile.go (100%) rename lib/util/{ => encoding}/ini/unmarshal.go (100%) rename lib/util/{ => encoding}/ini/unmarshal_test.go (100%) create mode 100644 lib/util/encoding/userlist/unmarshal.go create mode 100644 pgbouncer.ini create mode 100644 userlist.txt diff --git a/lib/bouncer/backends/v0/accept.go b/lib/bouncer/backends/v0/accept.go index 49c2866d..e9ff29b4 100644 --- a/lib/bouncer/backends/v0/accept.go +++ b/lib/bouncer/backends/v0/accept.go @@ -223,7 +223,7 @@ func startup1(server zap.ReadWriter, parameterStatus map[string]string) (done bo return false, nil default: err = ErrUnexpectedPacket - return false, err + return } } diff --git a/lib/gat/configs/pgbouncer/config.go b/lib/gat/configs/pgbouncer/config.go index aa464449..b52d3a50 100644 --- a/lib/gat/configs/pgbouncer/config.go +++ b/lib/gat/configs/pgbouncer/config.go @@ -2,14 +2,17 @@ package pgbouncer import ( "errors" + "log" "net" + "os" "strconv" "time" "pggat2/lib/gat" "pggat2/lib/gat/pools/session" "pggat2/lib/gat/pools/transaction" - "pggat2/lib/util/ini" + ini2 "pggat2/lib/util/encoding/ini" + "pggat2/lib/util/encoding/userlist" ) type PoolMode string @@ -248,19 +251,32 @@ var Default = Config{ } func Load() (Config, error) { - conf, err := ini.ReadFile("pgbouncer.ini") + conf, err := ini2.ReadFile("pgbouncer.ini") if err != nil { return Config{}, err } var c = Default - err = ini.Unmarshal(conf, &c) + err = ini2.Unmarshal(conf, &c) return c, err } func (T *Config) ListenAndServe(pooler *gat.Pooler) error { + var authFile map[string]string + if T.PgBouncer.AuthFile != "" { + file, err := os.ReadFile(T.PgBouncer.AuthFile) + if err != nil { + return err + } + + authFile, err = userlist.Unmarshal(file) + if err != nil { + return err + } + } + for name, user := range T.Users { - u := gat.NewUser("pw") // TODO(garet) passwords + u := gat.NewUser(authFile[name]) // TODO(garet) passwords pooler.AddUser(name, u) for dbname, db := range T.Databases { @@ -305,12 +321,27 @@ func (T *Config) ListenAndServe(pooler *gat.Pooler) error { // connect over unix socket // TODO(garet) } else { + var address string + if db.Port == 0 { + address = net.JoinHostPort(db.Host, "5432") + } else { + address = net.JoinHostPort(db.Host, strconv.Itoa(db.Port)) + } + + var password string + if db.Password == "" { + // lookup password + password = authFile[name] + } else { + password = db.Password + } + // connect over tcp recipe := gat.TCPRecipe{ Database: db.DBName, - Address: db.Host, + Address: address, User: name, - Password: "pw", + Password: password, MinConnections: db.MinPoolSize, MaxConnections: db.MaxDBConnections, StartupParameters: startupParameters, @@ -327,7 +358,9 @@ func (T *Config) ListenAndServe(pooler *gat.Pooler) error { } } - return pooler.ListenAndServe( - net.JoinHostPort(T.PgBouncer.ListenAddr, strconv.Itoa(T.PgBouncer.ListenPort)), - ) + listen := net.JoinHostPort(T.PgBouncer.ListenAddr, strconv.Itoa(T.PgBouncer.ListenPort)) + + log.Println("listening on", listen) + + return pooler.ListenAndServe(listen) } diff --git a/lib/gat/pool.go b/lib/gat/pool.go index d72bf5b8..faed75e1 100644 --- a/lib/gat/pool.go +++ b/lib/gat/pool.go @@ -57,29 +57,31 @@ func NewPool(raw RawPool, idleTimeout time.Duration) *Pool { } }() - go func() { - for { - var wait time.Duration + if idleTimeout != 0 { + go func() { + for { + var wait time.Duration + + now := time.Now() + idle := pool.IdleSince() + for now.Sub(idle) > idleTimeout { + if idle == (time.Time{}) { + break + } + pool.ScaleDown(1) + idle = pool.IdleSince() + } - now := time.Now() - idle := pool.IdleSince() - for now.Sub(idle) > idleTimeout { if idle == (time.Time{}) { - break + wait = idleTimeout + } else { + wait = now.Sub(idle.Add(idleTimeout)) } - pool.ScaleDown(1) - idle = pool.IdleSince() - } - if idle == (time.Time{}) { - wait = idleTimeout - } else { - wait = now.Sub(idle.Add(idleTimeout)) + time.Sleep(wait) } - - time.Sleep(wait) - } - }() + }() + } return pool } diff --git a/lib/util/ini/readfile.go b/lib/util/encoding/ini/readfile.go similarity index 100% rename from lib/util/ini/readfile.go rename to lib/util/encoding/ini/readfile.go diff --git a/lib/util/ini/unmarshal.go b/lib/util/encoding/ini/unmarshal.go similarity index 100% rename from lib/util/ini/unmarshal.go rename to lib/util/encoding/ini/unmarshal.go diff --git a/lib/util/ini/unmarshal_test.go b/lib/util/encoding/ini/unmarshal_test.go similarity index 100% rename from lib/util/ini/unmarshal_test.go rename to lib/util/encoding/ini/unmarshal_test.go diff --git a/lib/util/encoding/userlist/unmarshal.go b/lib/util/encoding/userlist/unmarshal.go new file mode 100644 index 00000000..94444d2b --- /dev/null +++ b/lib/util/encoding/userlist/unmarshal.go @@ -0,0 +1,42 @@ +package userlist + +import ( + "bytes" + "errors" + "strconv" +) + +func Unmarshal(data []byte) (map[string]string, error) { + var res = make(map[string]string) + + var line []byte + for { + line, data, _ = bytes.Cut(data, []byte{'\n'}) + line = bytes.TrimSpace(line) + if len(line) == 0 { + if len(data) == 0 { + break + } + + continue + } + + fields := bytes.Fields(line) + if len(fields) < 2 { + return nil, errors.New("expected \"key\" \"value\"") + } + + key, err := strconv.Unquote(string(fields[0])) + if err != nil { + return nil, err + } + value, err := strconv.Unquote(string(fields[1])) + if err != nil { + return nil, err + } + + res[key] = value + } + + return res, nil +} diff --git a/pgbouncer.ini b/pgbouncer.ini new file mode 100644 index 00000000..5ce00217 --- /dev/null +++ b/pgbouncer.ini @@ -0,0 +1,10 @@ +[pgbouncer] +mode = transaction +auth_file = userlist.txt + +[users] +postgres = + +[databases] +uniswap = host=localhost +postgres = host=localhost diff --git a/userlist.txt b/userlist.txt new file mode 100644 index 00000000..7ceb0c53 --- /dev/null +++ b/userlist.txt @@ -0,0 +1 @@ +"postgres" "password" -- GitLab