Skip to content

Commit

Permalink
fix: add back postgrest anon role for canary-checker
Browse files Browse the repository at this point in the history
  • Loading branch information
moshloop committed Sep 12, 2024
1 parent 2745def commit 203f9fb
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 37 deletions.
28 changes: 15 additions & 13 deletions api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import (

var DefaultConfig = Config{
Postgrest: PostgrestConfig{
Version: "v10.0.0",
DBRole: "postgrest_api",
Port: 3000,
AdminPort: 3001,
MaxRows: 2000,
Version: "v10.0.0",
DBRole: "postgrest_api",
AnonDBRole: "",
Port: 3000,
AdminPort: 3001,
MaxRows: 2000,
},
}

Expand Down Expand Up @@ -110,14 +111,15 @@ func (c Config) GetUsername() string {
}

type PostgrestConfig struct {
Port int
Disable bool
LogLevel string
URL string
Version string
JWTSecret string
DBRole string
AdminPort int
Port int
Disable bool
LogLevel string
URL string
Version string
JWTSecret string
DBRole string
AnonDBRole string
AdminPort int

// A hard limit to the number of rows PostgREST will fetch from a view, table, or stored procedure.
// Limits payload size for accidental or malicious requests.
Expand Down
6 changes: 6 additions & 0 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,12 @@ func setStatementTimeouts(ctx dutyContext.Context, config api.Config) {
logger.Errorf(err.Error())
}

if config.Postgrest.AnonDBRole != "" {
if err := ctx.DB().Raw(fmt.Sprintf(`ALTER ROLE %s SET statement_timeout = '%0fs'`, config.Postgrest.AnonDBRole, postgrestTimeout.Seconds())).Error; err != nil {
logger.Errorf(err.Error())
}
}

statementTimeout := ctx.Properties().Duration("db.connection.timeout", 1*time.Hour)
if username := config.GetUsername(); username != "" {
if err := ctx.DB().Raw(fmt.Sprintf(`ALTER ROLE %s SET statement_timeout = '%0fs'`, username, statementTimeout.Seconds())).Error; err != nil {
Expand Down
2 changes: 2 additions & 0 deletions functions/postgrest.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ BEGIN

IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'postgrest_anon') THEN
CREATE ROLE postgrest_anon;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO postgrest_anon;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO postgrest_anon;
END IF;
END $$;
69 changes: 46 additions & 23 deletions migrate/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,40 +86,63 @@ func RunMigrations(pool *sql.DB, config api.Config) error {
return nil
}

func grantPostgrestRolesToCurrentUser(pool *sql.DB, config api.Config) error {
l := logger.GetLogger("migrate")

user := config.GetUsername()
if user == "" {
return fmt.Errorf("Cannot find username in connection string")
func createRole(db *sql.DB, roleName string, config api.Config, grants ...string) error {
if roleName == "" {
return nil
}
role := config.Postgrest.DBRole
if isPostgrestAPIGranted, err := checkIfRoleIsGranted(pool, role, user); err != nil {
log := logger.GetLogger("migrate")
count := 0
if err := db.QueryRow("SELECT count(*) FROM pg_catalog.pg_roles WHERE rolname = $1 LIMIT 1", roleName).Scan(&count); err != nil {
return err
} else if !isPostgrestAPIGranted {
if _, err := pool.Exec(fmt.Sprintf(`GRANT %s TO "%s"`, role, user)); err != nil {
} else if count == 0 {
if _, err := db.Exec(fmt.Sprintf("CREATE ROLE %s", roleName)); err != nil {
return err
} else {
log.Infof("Created role %s", roleName)
}
}
user := config.GetUsername()
if user == "" {
log.Errorf("Unable to find current user, %s may not be setup correctly", roleName)
} else {
if granted, err := checkIfRoleIsGranted(db, roleName, user); err != nil {
return err
} else if !granted {
if _, err := db.Exec(fmt.Sprintf(`GRANT %s TO "%s"`, roleName, user)); err != nil {
log.Errorf("Failed to grant role %s to %s", roleName, user)
} else {
log.Infof("Granted %s to %s", roleName, user)
}
}
l.Debugf("Granted %s to %s", role, user)

grantQuery := `
ALTER ROLE %s SET statement_timeout = '120s';
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO %s;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO %s;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO %s;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO %s;
`
grantQuery = fmt.Sprintf(grantQuery, role, role, role, role, role)
if _, err := pool.Exec(grantQuery); err != nil {
return oops.Hint(grantQuery).Wrap(err)
}

for _, grant := range grants {
if _, err := db.Exec(fmt.Sprintf(grant, roleName)); err != nil {
log.Errorf("Failed to apply grants for %s: %+v", roleName, err)
}
l.Debugf("Granted privileges to %s", user)

}

return nil
}

func grantPostgrestRolesToCurrentUser(pool *sql.DB, config api.Config) error {
if err := createRole(pool, config.Postgrest.DBRole, config,
"GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO %s",
"GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO %s",
"GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO %s",
"ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO %s"); err != nil {
return err
}
if err := createRole(pool, config.Postgrest.AnonDBRole, config,
"GRANT SELECT ON ALL TABLES IN SCHEMA public TO %s",
"ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO %s"); err != nil {
return err
}

return nil
}

func checkIfRoleIsGranted(pool *sql.DB, group, member string) (bool, error) {
query := `
SELECT COUNT(*)
Expand Down
2 changes: 1 addition & 1 deletion postgrest/postgrest.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func getBinary(config api.Config) deps.BinaryFunc {
"PGRST_SERVER_PORT": strconv.Itoa(config.Postgrest.Port),
"PGRST_DB_URI": config.ConnectionString,
"PGRST_DB_SCHEMA": config.Schema,
"PGRST_DB_ANON_ROLE": "",
"PGRST_DB_ANON_ROLE": config.Postgrest.AnonDBRole,
"PGRST_OPENAPI_SERVER_PROXY_URI": config.Postgrest.URL,
"PGRST_LOG_LEVEL": config.Postgrest.LogLevel,
"PGRST_DB_MAX_ROWS": strconv.Itoa(config.Postgrest.MaxRows),
Expand Down
2 changes: 2 additions & 0 deletions start.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ func BindPFlags(flags *pflag.FlagSet, opts ...StartOption) {
flags.StringVar(&DefaultConfig.Postgrest.JWTSecret, "postgrest-jwt-secret", "PGRST_JWT_SECRET", "JWT Secret Token for PostgREST")
flags.BoolVar(&DefaultConfig.Postgrest.Disable, "disable-postgrest", config.Postgrest.Disable, "Disable PostgREST. Deprecated (Use --postgrest-uri '' to disable PostgREST)")
flags.StringVar(&DefaultConfig.Postgrest.DBRole, "postgrest-role", "postgrest_api", "PostgREST role for authentication connections")
flags.StringVar(&DefaultConfig.Postgrest.AnonDBRole, "postgrest-anon-role", "postgrest_anon", "PostgREST role for unauthenticated connections")

flags.IntVar(&DefaultConfig.Postgrest.MaxRows, "postgrest-max-rows", 2000, "A hard limit to the number of rows PostgREST will fetch")
flags.StringVar(&DefaultConfig.LogLevel, "db-log-level", "error", "Set gorm logging level. trace, debug & info")
flags.BoolVar(&DefaultConfig.DisableKubernetes, "disable-kubernetes", false, "Disable Kubernetes integration")
Expand Down

0 comments on commit 203f9fb

Please sign in to comment.