postgres: replace the package lib/pq with pgx (#15343)

* WIP replacing lib/pq

* change timezome param to be URI format

* add changelog

* add changelog for redshift

* update changelog

* add test for DSN style connection string

* more parseurl and quoteidentify to sdk; include copyright and license

* call dbutil.ParseURL instead, fix import ordering

Co-authored-by: Calvin Leung Huang <1883212+calvn@users.noreply.github.com>
This commit is contained in:
Jim Kalafut
2022-05-23 12:49:18 -07:00
committed by GitHub
parent 4f21baa69a
commit c5a88aa1a6
23 changed files with 350 additions and 110 deletions

View File

@@ -9,16 +9,16 @@ import (
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-secure-stdlib/strutil"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/helper/connutil"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/vault/sdk/helper/dbtxn"
"github.com/hashicorp/vault/sdk/helper/template"
"github.com/lib/pq"
_ "github.com/jackc/pgx/v4/stdlib"
)
const (
postgreSQLTypeName = "postgres"
postgreSQLTypeName = "pgx"
defaultExpirationStatement = `
ALTER ROLE "{{name}}" VALID UNTIL '{{expiration}}';
`
@@ -396,27 +396,27 @@ func (p *PostgreSQL) defaultDeleteUser(ctx context.Context, username string) err
}
revocationStmts = append(revocationStmts, fmt.Sprintf(
`REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA %s FROM %s;`,
pq.QuoteIdentifier(schema),
pq.QuoteIdentifier(username)))
(schema),
dbutil.QuoteIdentifier(username)))
revocationStmts = append(revocationStmts, fmt.Sprintf(
`REVOKE USAGE ON SCHEMA %s FROM %s;`,
pq.QuoteIdentifier(schema),
pq.QuoteIdentifier(username)))
dbutil.QuoteIdentifier(schema),
dbutil.QuoteIdentifier(username)))
}
// for good measure, revoke all privileges and usage on schema public
revocationStmts = append(revocationStmts, fmt.Sprintf(
`REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM %s;`,
pq.QuoteIdentifier(username)))
dbutil.QuoteIdentifier(username)))
revocationStmts = append(revocationStmts, fmt.Sprintf(
"REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM %s;",
pq.QuoteIdentifier(username)))
dbutil.QuoteIdentifier(username)))
revocationStmts = append(revocationStmts, fmt.Sprintf(
"REVOKE USAGE ON SCHEMA public FROM %s;",
pq.QuoteIdentifier(username)))
dbutil.QuoteIdentifier(username)))
// get the current database name so we can issue a REVOKE CONNECT for
// this username
@@ -428,8 +428,8 @@ func (p *PostgreSQL) defaultDeleteUser(ctx context.Context, username string) err
if dbname.Valid {
revocationStmts = append(revocationStmts, fmt.Sprintf(
`REVOKE CONNECT ON DATABASE %s FROM %s;`,
pq.QuoteIdentifier(dbname.String),
pq.QuoteIdentifier(username)))
dbutil.QuoteIdentifier(dbname.String),
dbutil.QuoteIdentifier(username)))
}
// again, here, we do not stop on error, as we want to remove as
@@ -451,7 +451,7 @@ func (p *PostgreSQL) defaultDeleteUser(ctx context.Context, username string) err
// Drop this user
stmt, err = db.PrepareContext(ctx, fmt.Sprintf(
`DROP ROLE IF EXISTS %s;`, pq.QuoteIdentifier(username)))
`DROP ROLE IF EXISTS %s;`, dbutil.QuoteIdentifier(username)))
if err != nil {
return err
}

View File

@@ -8,8 +8,10 @@ import (
"testing"
"time"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/vault/helper/testhelpers/postgresql"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5"
dbtesting "github.com/hashicorp/vault/sdk/database/dbplugin/v5/testing"
"github.com/hashicorp/vault/sdk/helper/template"
"github.com/stretchr/testify/require"
@@ -61,6 +63,32 @@ func TestPostgreSQL_InitializeWithStringVals(t *testing.T) {
}
}
func TestPostgreSQL_Initialize_ConnURLWithDSNFormat(t *testing.T) {
cleanup, connURL := postgresql.PrepareTestContainer(t, "13.4-buster")
defer cleanup()
dsnConnURL, err := dbutil.ParseURL(connURL)
if err != nil {
t.Fatal(err)
}
connectionDetails := map[string]interface{}{
"connection_url": dsnConnURL,
}
req := dbplugin.InitializeRequest{
Config: connectionDetails,
VerifyConnection: true,
}
db := new()
dbtesting.AssertInitialize(t, db, req)
if !db.Initialized {
t.Fatal("Database should be initialized")
}
}
func TestPostgreSQL_NewUser(t *testing.T) {
type testCase struct {
req dbplugin.NewUserRequest
@@ -675,7 +703,7 @@ func testCredsExist(t testing.TB, connURL, username, password string) error {
t.Helper()
// Log in with the new creds
connURL = strings.Replace(connURL, "postgres:secret", fmt.Sprintf("%s:%s", username, password), 1)
db, err := sql.Open("postgres", connURL)
db, err := sql.Open("pgx", connURL)
if err != nil {
return err
}