From f3c14cc18daa678a0b2026d7dee67499ae0c9c98 Mon Sep 17 00:00:00 2001 From: Garet Halliday <ghalliday@gfxlabs.io> Date: Wed, 21 Sep 2022 16:43:16 -0500 Subject: [PATCH] fix potential panic if pggat is configured wrong --- Dockerfile | 6 +++ config_data.yml | 6 +-- lib/gat/gatling/client/client.go | 12 +++--- lib/gat/gatling/server/server_test.go | 10 +++-- lib/gat/pool/session/pool.go | 53 ++++++++++++++++++++------- test/Dockerfile | 19 ---------- test/docker-compose.yml | 11 +++++- 7 files changed, 70 insertions(+), 47 deletions(-) create mode 100644 Dockerfile delete mode 100644 test/Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..3179a291 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM golang + +WORKDIR /wd +COPY . /wd +RUN go build ./cmd/cgat +ENTRYPOINT ["./cgat"] diff --git a/config_data.yml b/config_data.yml index f80da562..f339a88b 100644 --- a/config_data.yml +++ b/config_data.yml @@ -13,7 +13,7 @@ general: admin_password: postgres pools: simple_db: - pool_mode: transaction + pool_mode: session default_role: primary query_parser_enabled: true primary_reads_enabled: true @@ -29,12 +29,12 @@ pools: statement_timeout: 0 database: postgres servers: - - host: localhost + - host: db port: 5432 role: primary username: postgres password: password - - host: localhost + - host: db role: replica port: 5432 username: postgres diff --git a/lib/gat/gatling/client/client.go b/lib/gat/gatling/client/client.go index 79ab36d1..8c6d1b82 100644 --- a/lib/gat/gatling/client/client.go +++ b/lib/gat/gatling/client/client.go @@ -266,7 +266,7 @@ func (c *Client) Accept(ctx context.Context) error { c.poolName, ok = params["database"] if !ok { return &pg_error.Error{ - Severity: pg_error.Fatal, + Severity: pg_error.Err, Code: pg_error.InvalidAuthorizationSpecification, Message: "param database required", } @@ -275,7 +275,7 @@ func (c *Client) Accept(ctx context.Context) error { c.username, ok = params["user"] if !ok { return &pg_error.Error{ - Severity: pg_error.Fatal, + Severity: pg_error.Err, Code: pg_error.InvalidAuthorizationSpecification, Message: "param user required", } @@ -286,7 +286,7 @@ func (c *Client) Accept(ctx context.Context) error { if c.conf.General.AdminOnly && !admin { c.log.Debug().Msg("rejected non admin, since admin only mode") return &pg_error.Error{ - Severity: pg_error.Fatal, + Severity: pg_error.Err, Code: pg_error.InvalidAuthorizationSpecification, Message: "rejected non admin", } @@ -319,7 +319,7 @@ func (c *Client) Accept(ctx context.Context) error { passwordResponse = r.Fields.Data default: return &pg_error.Error{ - Severity: pg_error.Fatal, + Severity: pg_error.Err, Code: pg_error.InvalidAuthorizationSpecification, Message: fmt.Sprintf("wanted AuthenticationResponse packet, got '%+v'", rsp), } @@ -342,7 +342,7 @@ func (c *Client) Accept(ctx context.Context) error { pw_hash := messages.Md5HashPassword(c.conf.General.AdminUsername, c.conf.General.AdminPassword, salt[:]) if !reflect.DeepEqual(pw_hash, passwordResponse) { return &pg_error.Error{ - Severity: pg_error.Fatal, + Severity: pg_error.Err, Code: pg_error.InvalidPassword, Message: "invalid password", } @@ -351,7 +351,7 @@ func (c *Client) Accept(ctx context.Context) error { pw_hash := messages.Md5HashPassword(c.username, user.Password, salt[:]) if !reflect.DeepEqual(pw_hash, passwordResponse) { return &pg_error.Error{ - Severity: pg_error.Fatal, + Severity: pg_error.Err, Code: pg_error.InvalidPassword, Message: "invalid password", } diff --git a/lib/gat/gatling/server/server_test.go b/lib/gat/gatling/server/server_test.go index b84d529c..3828290a 100644 --- a/lib/gat/gatling/server/server_test.go +++ b/lib/gat/gatling/server/server_test.go @@ -8,8 +8,12 @@ import ( "gfx.cafe/gfx/pggat/lib/config" ) -var test_address = "localhost" -var test_port uint16 = 5432 +var test_server = config.Server{ + Host: "localhost", + Port: 5432, +} + +var test_shard = config.Shard{} var test_user = config.User{ Name: "postgres", @@ -19,7 +23,7 @@ var test_user = config.User{ } func TestServerDial(t *testing.T) { - srv, err := Dial(context.TODO(), test_address, test_port, &test_user, "postgres", test_user.Name, test_user.Password) + srv, err := Dial(context.TODO(), &test_user, &test_shard, &test_server) if err != nil { t.Error(err) } diff --git a/lib/gat/pool/session/pool.go b/lib/gat/pool/session/pool.go index 7db5b7f3..49354e30 100644 --- a/lib/gat/pool/session/pool.go +++ b/lib/gat/pool/session/pool.go @@ -35,14 +35,13 @@ func New(database gat.Database, dialer gat.Dialer, conf *config.Pool, user *conf return p } -func (p *Pool) getConnection() gat.Connection { +func (p *Pool) getConnection() (gat.Connection, error) { select { case c := <-p.servers: - return c + return c, nil default: shard := p.c.Load().Shards[0] - s, _ := p.dialer(context.TODO(), p.user, shard, shard.Servers[0]) - return s + return p.dialer(context.TODO(), p.user, shard, shard.Servers[0]) } } @@ -50,15 +49,18 @@ func (p *Pool) returnConnection(c gat.Connection) { p.servers <- c } -func (p *Pool) getOrAssign(client gat.Client) gat.Connection { +func (p *Pool) getOrAssign(client gat.Client) (gat.Connection, error) { cid := client.GetId() c, ok := p.assigned.Load(cid) if !ok { - get := p.getConnection() + get, err := p.getConnection() + if err != nil { + return nil, err + } p.assigned.Store(cid, get) - return get + return get, err } - return c + return c, nil } func (p *Pool) GetDatabase() gat.Database { @@ -83,29 +85,52 @@ func (p *Pool) GetUser() *config.User { } func (p *Pool) GetServerInfo() []*protocol.ParameterStatus { - c := p.getConnection() + c, err := p.getConnection() + if err != nil { + return nil + } defer p.returnConnection(c) return c.GetServerInfo() } func (p *Pool) Describe(ctx context.Context, client gat.Client, describe *protocol.Describe) error { - return p.getOrAssign(client).Describe(client, describe) + c, err := p.getOrAssign(client) + if err != nil { + return err + } + return c.Describe(client, describe) } func (p *Pool) Execute(ctx context.Context, client gat.Client, execute *protocol.Execute) error { - return p.getOrAssign(client).Execute(client, execute) + c, err := p.getOrAssign(client) + if err != nil { + return err + } + return c.Execute(client, execute) } func (p *Pool) SimpleQuery(ctx context.Context, client gat.Client, query string) error { - return p.getOrAssign(client).SimpleQuery(ctx, client, query) + c, err := p.getOrAssign(client) + if err != nil { + return err + } + return c.SimpleQuery(ctx, client, query) } func (p *Pool) Transaction(ctx context.Context, client gat.Client, query string) error { - return p.getOrAssign(client).Transaction(ctx, client, query) + c, err := p.getOrAssign(client) + if err != nil { + return err + } + return c.Transaction(ctx, client, query) } func (p *Pool) CallFunction(ctx context.Context, client gat.Client, payload *protocol.FunctionCall) error { - return p.getOrAssign(client).CallFunction(client, payload) + c, err := p.getOrAssign(client) + if err != nil { + return err + } + return c.CallFunction(client, payload) } var _ gat.Pool = (*Pool)(nil) diff --git a/test/Dockerfile b/test/Dockerfile deleted file mode 100644 index db6c8499..00000000 --- a/test/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM postgres:14 - - -RUN apt-get update && apt-get upgrade - -RUN apt-get -y install git build-essential libreadline-dev zlib1g-dev flex bison libxml2-dev libxslt-dev libssl-dev libxml2-utils xsltproc ccache - - -WORKDIR /wd -RUN chown postgres:postgres /wd -USER postgres -RUN git clone https://github.com/postgres/postgres.git -WORKDIR /wd/postgres -RUN git checkout REL_14_STABLE -RUN ./configure -RUN make -USER root -RUN make install -USER postgres diff --git a/test/docker-compose.yml b/test/docker-compose.yml index dac58ba2..d10f7f8e 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -2,12 +2,19 @@ version: '3.9' services: db: - build: . + image: postgres restart: always environment: - POSTGRES_PASSWORD: example + POSTGRES_PASSWORD: exmaple + ports: + - 5432:5432 adminer: image: adminer restart: always ports: - 8080:8080 + pggat: + build: ../ + restart: always + ports: + - 6432:6432 -- GitLab