From 177d366f8123e58a9b0f024fe5306ef1ebc4137f Mon Sep 17 00:00:00 2001 From: Test Test959 <68299987+testtest959@users.noreply.github.com> Date: Tue, 16 Mar 2021 12:03:17 -0400 Subject: [PATCH 1/5] Squash commits --- database/pgx/pgx.go | 19 +++- database/pgx/pgx_test.go | 154 ++++++++++++++++++++++++++++ database/postgres/postgres.go | 19 +++- database/postgres/postgres_test.go | 157 ++++++++++++++++++++++++++++- 4 files changed, 345 insertions(+), 4 deletions(-) diff --git a/database/pgx/pgx.go b/database/pgx/pgx.go index 8e49638ed..06a37755b 100644 --- a/database/pgx/pgx.go +++ b/database/pgx/pgx.go @@ -429,7 +429,24 @@ func (p *Postgres) ensureVersionTable() (err error) { } }() - query := `CREATE TABLE IF NOT EXISTS ` + quoteIdentifier(p.config.MigrationsTable) + ` (version bigint not null primary key, dirty boolean not null)` + // This block checks whether the `MigrationsTable` already exists. This is useful because it allows read only postgres + // users to also check the current version of the schema. Previously, even if `MigrationsTable` existed, the + // `CREATE TABLE IF NOT EXISTS...` query would fail because the user does not have the CREATE permission. + // Taken from https://github.com/mattes/migrate/blob/master/database/postgres/postgres.go#L258 + var count int + query := `SELECT COUNT(1) FROM information_schema.tables WHERE table_name = $1 AND table_schema = (SELECT current_schema()) LIMIT 1` + row := p.conn.QueryRowContext(context.Background(), query, p.config.MigrationsTable); + + err = row.Scan(&count) + if err != nil { + return &database.Error{OrigErr: err, Query: []byte(query)} + } + + if count == 1 { + return nil + } + + query = `CREATE TABLE IF NOT EXISTS ` + quoteIdentifier(p.config.MigrationsTable) + ` (version bigint not null primary key, dirty boolean not null)` if _, err = p.conn.ExecContext(context.Background(), query); err != nil { return &database.Error{OrigErr: err, Query: []byte(query)} } diff --git a/database/pgx/pgx_test.go b/database/pgx/pgx_test.go index ec58c4aae..5ba68c0ad 100644 --- a/database/pgx/pgx_test.go +++ b/database/pgx/pgx_test.go @@ -6,6 +6,7 @@ import ( "context" "database/sql" sqldriver "database/sql/driver" + "errors" "fmt" "log" @@ -309,6 +310,159 @@ func TestWithSchema(t *testing.T) { }) } +func TestFailToCreateTableWithoutPermissions(t *testing.T) { + dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { + ip, port, err := c.FirstPort() + if err != nil { + t.Fatal(err) + } + + addr := pgConnectionString(ip, port) + + // Check that opening the postgres connection returns NilVersion + p := &Postgres{} + + d, err := p.Open(addr) + + if err != nil { + t.Fatal(err) + } + + defer func() { + if err := d.Close(); err != nil { + t.Error(err) + } + }() + + // create user who is not the owner. Although we're concatenating strings in an sql statement it should be fine + // since this is a test environment and we're not expecting to the pgPassword to be malicious + if err := d.Run(strings.NewReader("CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'")); err != nil { + t.Fatal(err) + } + + // create foobar schema + if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { + t.Fatal(err) + } + + // revoke privileges + if err := d.Run(strings.NewReader("GRANT USAGE ON SCHEMA barfoo TO not_owner")); err != nil { + t.Fatal(err) + } + if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC")); err != nil { + t.Fatal(err) + } + if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM not_owner")); err != nil { + t.Fatal(err) + } + + // re-connect using that schema + d2, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", + pgPassword, ip, port)) + + defer func() { + if d2 == nil { + return + } + if err := d2.Close(); err != nil { + t.Fatal(err) + } + }() + + var e *database.Error + if !errors.As(err, &e) || err == nil { + t.Fatal("Unexpected error, want permission denied error. Got: ", err) + } + }) +} + +func TestCheckBeforeCreateTable(t *testing.T) { + dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { + ip, port, err := c.FirstPort() + if err != nil { + t.Fatal(err) + } + + addr := pgConnectionString(ip, port) + + // Check that opening the postgres connection returns NilVersion + p := &Postgres{} + + d, err := p.Open(addr) + + if err != nil { + t.Fatal(err) + } + + defer func() { + if err := d.Close(); err != nil { + t.Error(err) + } + }() + + // create user who is not the owner. Although we're concatenating strings in an sql statement it should be fine + // since this is a test environment and we're not expecting to the pgPassword to be malicious + if err := d.Run(strings.NewReader("CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'")); err != nil { + t.Fatal(err) + } + + // create foobar schema + if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { + t.Fatal(err) + } + if err := d.Run(strings.NewReader("GRANT USAGE ON SCHEMA barfoo TO not_owner")); err != nil { + t.Fatal(err) + } + if err := d.Run(strings.NewReader("GRANT CREATE ON SCHEMA barfoo TO not_owner")); err != nil { + t.Fatal(err) + } + + // re-connect using that schema + d2, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", + pgPassword, ip, port)) + + if err != nil { + t.Fatal(err) + } + + if err := d2.Close(); err != nil { + t.Fatal(err) + } + + // revoke privileges + if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC")); err != nil { + t.Fatal(err) + } + if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM not_owner")); err != nil { + t.Fatal(err) + } + + // re-connect using that schema + d3, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", + pgPassword, ip, port)) + + if err != nil { + t.Fatal(err) + } + + version, _, err := d3.Version() + + if err != nil { + t.Fatal(err) + } + + if version != database.NilVersion { + t.Fatal("Unexpected version, want database.NilVersion. Got: ", version) + } + + defer func() { + if err := d3.Close(); err != nil { + t.Fatal(err) + } + }() + }) +} + func TestParallelSchema(t *testing.T) { dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { ip, port, err := c.FirstPort() diff --git a/database/postgres/postgres.go b/database/postgres/postgres.go index 0432db223..7641c06f0 100644 --- a/database/postgres/postgres.go +++ b/database/postgres/postgres.go @@ -426,7 +426,24 @@ func (p *Postgres) ensureVersionTable() (err error) { } }() - query := `CREATE TABLE IF NOT EXISTS ` + pq.QuoteIdentifier(p.config.MigrationsTable) + ` (version bigint not null primary key, dirty boolean not null)` + // This block checks whether the `MigrationsTable` already exists. This is useful because it allows read only postgres + // users to also check the current version of the schema. Previously, even if `MigrationsTable` existed, the + // `CREATE TABLE IF NOT EXISTS...` query would fail because the user does not have the CREATE permission. + // Taken from https://github.com/mattes/migrate/blob/master/database/postgres/postgres.go#L258 + var count int + query := `SELECT COUNT(1) FROM information_schema.tables WHERE table_name = $1 AND table_schema = (SELECT current_schema()) LIMIT 1` + row := p.conn.QueryRowContext(context.Background(), query, p.config.MigrationsTable); + + err = row.Scan(&count) + if err != nil { + return &database.Error{OrigErr: err, Query: []byte(query)} + } + + if count == 1 { + return nil + } + + query = `CREATE TABLE IF NOT EXISTS ` + pq.QuoteIdentifier(p.config.MigrationsTable) + ` (version bigint not null primary key, dirty boolean not null)` if _, err = p.conn.ExecContext(context.Background(), query); err != nil { return &database.Error{OrigErr: err, Query: []byte(query)} } diff --git a/database/postgres/postgres_test.go b/database/postgres/postgres_test.go index 3d2661f26..37c135c4b 100644 --- a/database/postgres/postgres_test.go +++ b/database/postgres/postgres_test.go @@ -6,11 +6,11 @@ import ( "context" "database/sql" sqldriver "database/sql/driver" + "errors" "fmt" - "log" - "github.com/golang-migrate/migrate/v4" "io" + "log" "strconv" "strings" "sync" @@ -310,6 +310,159 @@ func TestWithSchema(t *testing.T) { }) } +func TestFailToCreateTableWithoutPermissions(t *testing.T) { + dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { + ip, port, err := c.FirstPort() + if err != nil { + t.Fatal(err) + } + + addr := pgConnectionString(ip, port) + + // Check that opening the postgres connection returns NilVersion + p := &Postgres{} + + d, err := p.Open(addr) + + if err != nil { + t.Fatal(err) + } + + defer func() { + if err := d.Close(); err != nil { + t.Error(err) + } + }() + + // create user who is not the owner. Although we're concatenating strings in an sql statement it should be fine + // since this is a test environment and we're not expecting to the pgPassword to be malicious + if err := d.Run(strings.NewReader("CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'")); err != nil { + t.Fatal(err) + } + + // create foobar schema + if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { + t.Fatal(err) + } + + // revoke privileges + if err := d.Run(strings.NewReader("GRANT USAGE ON SCHEMA barfoo TO not_owner")); err != nil { + t.Fatal(err) + } + if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC")); err != nil { + t.Fatal(err) + } + if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM not_owner")); err != nil { + t.Fatal(err) + } + + // re-connect using that schema + d2, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", + pgPassword, ip, port)) + + defer func() { + if d2 == nil { + return + } + if err := d2.Close(); err != nil { + t.Fatal(err) + } + }() + + var e *database.Error + if !errors.As(err, &e) || err == nil { + t.Fatal("Unexpected error, want permission denied error. Got: ", err) + } + }) +} + +func TestCheckBeforeCreateTable(t *testing.T) { + dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { + ip, port, err := c.FirstPort() + if err != nil { + t.Fatal(err) + } + + addr := pgConnectionString(ip, port) + + // Check that opening the postgres connection returns NilVersion + p := &Postgres{} + + d, err := p.Open(addr) + + if err != nil { + t.Fatal(err) + } + + defer func() { + if err := d.Close(); err != nil { + t.Error(err) + } + }() + + // create user who is not the owner. Although we're concatenating strings in an sql statement it should be fine + // since this is a test environment and we're not expecting to the pgPassword to be malicious + if err := d.Run(strings.NewReader("CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'")); err != nil { + t.Fatal(err) + } + + // create foobar schema + if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { + t.Fatal(err) + } + if err := d.Run(strings.NewReader("GRANT USAGE ON SCHEMA barfoo TO not_owner")); err != nil { + t.Fatal(err) + } + if err := d.Run(strings.NewReader("GRANT CREATE ON SCHEMA barfoo TO not_owner")); err != nil { + t.Fatal(err) + } + + // re-connect using that schema + d2, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", + pgPassword, ip, port)) + + if err != nil { + t.Fatal(err) + } + + if err := d2.Close(); err != nil { + t.Fatal(err) + } + + // revoke privileges + if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC")); err != nil { + t.Fatal(err) + } + if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM not_owner")); err != nil { + t.Fatal(err) + } + + // re-connect using that schema + d3, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", + pgPassword, ip, port)) + + if err != nil { + t.Fatal(err) + } + + version, _, err := d3.Version() + + if err != nil { + t.Fatal(err) + } + + if version != database.NilVersion { + t.Fatal("Unexpected version, want database.NilVersion. Got: ", version) + } + + defer func() { + if err := d3.Close(); err != nil { + t.Fatal(err) + } + }() + }) +} + func TestParallelSchema(t *testing.T) { dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { ip, port, err := c.FirstPort() From ff6799759c04370468665e0577800138a52d32c1 Mon Sep 17 00:00:00 2001 From: Test Test959 <68299987+testtest959@users.noreply.github.com> Date: Tue, 16 Mar 2021 12:48:07 -0400 Subject: [PATCH 2/5] Format --- database/pgx/pgx.go | 2 +- database/postgres/postgres.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/database/pgx/pgx.go b/database/pgx/pgx.go index 06a37755b..dda70a77c 100644 --- a/database/pgx/pgx.go +++ b/database/pgx/pgx.go @@ -435,7 +435,7 @@ func (p *Postgres) ensureVersionTable() (err error) { // Taken from https://github.com/mattes/migrate/blob/master/database/postgres/postgres.go#L258 var count int query := `SELECT COUNT(1) FROM information_schema.tables WHERE table_name = $1 AND table_schema = (SELECT current_schema()) LIMIT 1` - row := p.conn.QueryRowContext(context.Background(), query, p.config.MigrationsTable); + row := p.conn.QueryRowContext(context.Background(), query, p.config.MigrationsTable) err = row.Scan(&count) if err != nil { diff --git a/database/postgres/postgres.go b/database/postgres/postgres.go index 7641c06f0..4926e1d84 100644 --- a/database/postgres/postgres.go +++ b/database/postgres/postgres.go @@ -432,7 +432,7 @@ func (p *Postgres) ensureVersionTable() (err error) { // Taken from https://github.com/mattes/migrate/blob/master/database/postgres/postgres.go#L258 var count int query := `SELECT COUNT(1) FROM information_schema.tables WHERE table_name = $1 AND table_schema = (SELECT current_schema()) LIMIT 1` - row := p.conn.QueryRowContext(context.Background(), query, p.config.MigrationsTable); + row := p.conn.QueryRowContext(context.Background(), query, p.config.MigrationsTable) err = row.Scan(&count) if err != nil { From 0c748e23f4bd175e6db67385bac70117c29a0839 Mon Sep 17 00:00:00 2001 From: Test Test959 <68299987+testtest959@users.noreply.github.com> Date: Tue, 16 Mar 2021 14:15:10 -0400 Subject: [PATCH 3/5] Minor refactoring --- database/pgx/pgx_test.go | 8 ++------ database/postgres/postgres_test.go | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/database/pgx/pgx_test.go b/database/pgx/pgx_test.go index 5ba68c0ad..ba73a7308 100644 --- a/database/pgx/pgx_test.go +++ b/database/pgx/pgx_test.go @@ -340,7 +340,7 @@ func TestFailToCreateTableWithoutPermissions(t *testing.T) { t.Fatal(err) } - // create foobar schema + // create barfoo schema if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { t.Fatal(err) } @@ -406,7 +406,7 @@ func TestCheckBeforeCreateTable(t *testing.T) { t.Fatal(err) } - // create foobar schema + // create barfoo schema if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { t.Fatal(err) } @@ -529,10 +529,6 @@ func TestParallelSchema(t *testing.T) { }) } -func TestWithInstance(t *testing.T) { - -} - func TestPostgres_Lock(t *testing.T) { dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { ip, port, err := c.FirstPort() diff --git a/database/postgres/postgres_test.go b/database/postgres/postgres_test.go index 37c135c4b..791bf67be 100644 --- a/database/postgres/postgres_test.go +++ b/database/postgres/postgres_test.go @@ -340,7 +340,7 @@ func TestFailToCreateTableWithoutPermissions(t *testing.T) { t.Fatal(err) } - // create foobar schema + // create barfoo schema if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { t.Fatal(err) } @@ -406,7 +406,7 @@ func TestCheckBeforeCreateTable(t *testing.T) { t.Fatal(err) } - // create foobar schema + // create barfoo schema if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { t.Fatal(err) } @@ -531,10 +531,6 @@ func TestParallelSchema(t *testing.T) { }) } -func TestWithInstance(t *testing.T) { - -} - func TestPostgres_Lock(t *testing.T) { dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { ip, port, err := c.FirstPort() From 97888376e0649d66f45d58acb1810f97e2e3d1aa Mon Sep 17 00:00:00 2001 From: Test Test959 <68299987+testtest959@users.noreply.github.com> Date: Wed, 17 Mar 2021 11:04:23 -0400 Subject: [PATCH 4/5] Address PR feedback; Add mustRun --- database/pgx/pgx_test.go | 68 +++++++++++++----------------- database/postgres/postgres_test.go | 68 +++++++++++++----------------- 2 files changed, 58 insertions(+), 78 deletions(-) diff --git a/database/pgx/pgx_test.go b/database/pgx/pgx_test.go index ba73a7308..eb3b6199d 100644 --- a/database/pgx/pgx_test.go +++ b/database/pgx/pgx_test.go @@ -77,6 +77,14 @@ func isReady(ctx context.Context, c dktest.ContainerInfo) bool { return true } +func mustRun(t *testing.T, d database.Driver, statements []string) { + for _, statement := range statements { + if err := d.Run(strings.NewReader(statement)); err != nil { + t.Fatal(err) + } + } +} + func Test(t *testing.T) { dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { ip, port, err := c.FirstPort() @@ -336,25 +344,13 @@ func TestFailToCreateTableWithoutPermissions(t *testing.T) { // create user who is not the owner. Although we're concatenating strings in an sql statement it should be fine // since this is a test environment and we're not expecting to the pgPassword to be malicious - if err := d.Run(strings.NewReader("CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'")); err != nil { - t.Fatal(err) - } - - // create barfoo schema - if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { - t.Fatal(err) - } - - // revoke privileges - if err := d.Run(strings.NewReader("GRANT USAGE ON SCHEMA barfoo TO not_owner")); err != nil { - t.Fatal(err) - } - if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC")); err != nil { - t.Fatal(err) - } - if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM not_owner")); err != nil { - t.Fatal(err) - } + mustRun(t, d, []string{ + "CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'", + "CREATE SCHEMA barfoo AUTHORIZATION postgres", + "GRANT USAGE ON SCHEMA barfoo TO not_owner", + "REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC", + "REVOKE CREATE ON SCHEMA barfoo FROM not_owner", + }) // re-connect using that schema d2, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", @@ -373,6 +369,10 @@ func TestFailToCreateTableWithoutPermissions(t *testing.T) { if !errors.As(err, &e) || err == nil { t.Fatal("Unexpected error, want permission denied error. Got: ", err) } + + if strings.Contains(e.Err, "permission denied for schema barfoo") { + t.Fatal(e) + } }) } @@ -402,20 +402,12 @@ func TestCheckBeforeCreateTable(t *testing.T) { // create user who is not the owner. Although we're concatenating strings in an sql statement it should be fine // since this is a test environment and we're not expecting to the pgPassword to be malicious - if err := d.Run(strings.NewReader("CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'")); err != nil { - t.Fatal(err) - } - - // create barfoo schema - if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { - t.Fatal(err) - } - if err := d.Run(strings.NewReader("GRANT USAGE ON SCHEMA barfoo TO not_owner")); err != nil { - t.Fatal(err) - } - if err := d.Run(strings.NewReader("GRANT CREATE ON SCHEMA barfoo TO not_owner")); err != nil { - t.Fatal(err) - } + mustRun(t, d, []string{ + "CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'", + "CREATE SCHEMA barfoo AUTHORIZATION postgres", + "GRANT USAGE ON SCHEMA barfoo TO not_owner", + "GRANT CREATE ON SCHEMA barfoo TO not_owner", + }) // re-connect using that schema d2, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", @@ -430,12 +422,10 @@ func TestCheckBeforeCreateTable(t *testing.T) { } // revoke privileges - if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC")); err != nil { - t.Fatal(err) - } - if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM not_owner")); err != nil { - t.Fatal(err) - } + mustRun(t, d, []string{ + "REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC", + "REVOKE CREATE ON SCHEMA barfoo FROM not_owner", + }) // re-connect using that schema d3, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", diff --git a/database/postgres/postgres_test.go b/database/postgres/postgres_test.go index 791bf67be..f154db2fb 100644 --- a/database/postgres/postgres_test.go +++ b/database/postgres/postgres_test.go @@ -75,6 +75,14 @@ func isReady(ctx context.Context, c dktest.ContainerInfo) bool { return true } +func mustRun(t *testing.T, d database.Driver, statements []string) { + for _, statement := range statements { + if err := d.Run(strings.NewReader(statement)); err != nil { + t.Fatal(err) + } + } +} + func Test(t *testing.T) { dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { ip, port, err := c.FirstPort() @@ -336,25 +344,13 @@ func TestFailToCreateTableWithoutPermissions(t *testing.T) { // create user who is not the owner. Although we're concatenating strings in an sql statement it should be fine // since this is a test environment and we're not expecting to the pgPassword to be malicious - if err := d.Run(strings.NewReader("CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'")); err != nil { - t.Fatal(err) - } - - // create barfoo schema - if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { - t.Fatal(err) - } - - // revoke privileges - if err := d.Run(strings.NewReader("GRANT USAGE ON SCHEMA barfoo TO not_owner")); err != nil { - t.Fatal(err) - } - if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC")); err != nil { - t.Fatal(err) - } - if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM not_owner")); err != nil { - t.Fatal(err) - } + mustRun(t, d, []string{ + "CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'", + "CREATE SCHEMA barfoo AUTHORIZATION postgres", + "GRANT USAGE ON SCHEMA barfoo TO not_owner", + "REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC", + "REVOKE CREATE ON SCHEMA barfoo FROM not_owner", + }) // re-connect using that schema d2, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", @@ -373,6 +369,10 @@ func TestFailToCreateTableWithoutPermissions(t *testing.T) { if !errors.As(err, &e) || err == nil { t.Fatal("Unexpected error, want permission denied error. Got: ", err) } + + if strings.Contains(e.Err, "permission denied for schema barfoo") { + t.Fatal(e) + } }) } @@ -402,20 +402,12 @@ func TestCheckBeforeCreateTable(t *testing.T) { // create user who is not the owner. Although we're concatenating strings in an sql statement it should be fine // since this is a test environment and we're not expecting to the pgPassword to be malicious - if err := d.Run(strings.NewReader("CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'")); err != nil { - t.Fatal(err) - } - - // create barfoo schema - if err := d.Run(strings.NewReader("CREATE SCHEMA barfoo AUTHORIZATION postgres")); err != nil { - t.Fatal(err) - } - if err := d.Run(strings.NewReader("GRANT USAGE ON SCHEMA barfoo TO not_owner")); err != nil { - t.Fatal(err) - } - if err := d.Run(strings.NewReader("GRANT CREATE ON SCHEMA barfoo TO not_owner")); err != nil { - t.Fatal(err) - } + mustRun(t, d, []string{ + "CREATE USER not_owner WITH ENCRYPTED PASSWORD '" + pgPassword + "'", + "CREATE SCHEMA barfoo AUTHORIZATION postgres", + "GRANT USAGE ON SCHEMA barfoo TO not_owner", + "GRANT CREATE ON SCHEMA barfoo TO not_owner", + }) // re-connect using that schema d2, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", @@ -430,12 +422,10 @@ func TestCheckBeforeCreateTable(t *testing.T) { } // revoke privileges - if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC")); err != nil { - t.Fatal(err) - } - if err := d.Run(strings.NewReader("REVOKE CREATE ON SCHEMA barfoo FROM not_owner")); err != nil { - t.Fatal(err) - } + mustRun(t, d, []string{ + "REVOKE CREATE ON SCHEMA barfoo FROM PUBLIC", + "REVOKE CREATE ON SCHEMA barfoo FROM not_owner", + }) // re-connect using that schema d3, err := p.Open(fmt.Sprintf("postgres://not_owner:%s@%v:%v/postgres?sslmode=disable&search_path=barfoo", From 8f15e2c85c6dc3023ff46dfe8c58aad86e4fe61f Mon Sep 17 00:00:00 2001 From: Test Test959 <68299987+testtest959@users.noreply.github.com> Date: Thu, 18 Mar 2021 09:52:15 -0400 Subject: [PATCH 5/5] Fix a test assert --- database/pgx/pgx_test.go | 2 +- database/postgres/postgres_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/database/pgx/pgx_test.go b/database/pgx/pgx_test.go index eb3b6199d..a79f9611e 100644 --- a/database/pgx/pgx_test.go +++ b/database/pgx/pgx_test.go @@ -370,7 +370,7 @@ func TestFailToCreateTableWithoutPermissions(t *testing.T) { t.Fatal("Unexpected error, want permission denied error. Got: ", err) } - if strings.Contains(e.Err, "permission denied for schema barfoo") { + if !strings.Contains(e.OrigErr.Error(), "permission denied for schema barfoo") { t.Fatal(e) } }) diff --git a/database/postgres/postgres_test.go b/database/postgres/postgres_test.go index f154db2fb..c6cc9e7f8 100644 --- a/database/postgres/postgres_test.go +++ b/database/postgres/postgres_test.go @@ -370,7 +370,7 @@ func TestFailToCreateTableWithoutPermissions(t *testing.T) { t.Fatal("Unexpected error, want permission denied error. Got: ", err) } - if strings.Contains(e.Err, "permission denied for schema barfoo") { + if !strings.Contains(e.OrigErr.Error(), "permission denied for schema barfoo") { t.Fatal(e) } })