diff --git a/pkg/cluster/database.go b/pkg/cluster/database.go index ba4cf223a..2ce0636b5 100644 --- a/pkg/cluster/database.go +++ b/pkg/cluster/database.go @@ -36,8 +36,8 @@ const ( createDatabaseSQL = `CREATE DATABASE "%s" OWNER "%s";` createDatabaseSchemaSQL = `SET ROLE TO "%s"; CREATE SCHEMA IF NOT EXISTS "%s" AUTHORIZATION "%s"` alterDatabaseOwnerSQL = `ALTER DATABASE "%s" OWNER TO "%s";` - createExtensionSQL = `CREATE EXTENSION IF NOT EXISTS "%s" SCHEMA "%s"` - alterExtensionSQL = `ALTER EXTENSION "%s" SET SCHEMA "%s"` + createExtensionSQL = `SET ROLE TO "%s"; CREATE EXTENSION IF NOT EXISTS "%s" SCHEMA "%s"` + alterExtensionSQL = `SET ROLE TO "%s"; ALTER EXTENSION "%s" SET SCHEMA "%s"` globalDefaultPrivilegesSQL = `SET ROLE TO "%s"; ALTER DEFAULT PRIVILEGES GRANT USAGE ON SCHEMAS TO "%s","%s"; @@ -56,6 +56,13 @@ const ( ALTER DEFAULT PRIVILEGES IN SCHEMA "%s" GRANT EXECUTE ON FUNCTIONS TO "%s","%s"; ALTER DEFAULT PRIVILEGES IN SCHEMA "%s" GRANT USAGE ON TYPES TO "%s","%s";` + extensionPostCreateSQL = ` + GRANT SELECT ON ALL TABLES IN SCHEMA "%s" TO "%s","%s"; + GRANT SELECT ON ALL SEQUENCES IN SCHEMA "%s" TO "%s","%s"; + GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA "%s" TO "%s","%s"; + GRANT USAGE, UPDATE ON ALL SEQUENCES IN SCHEMA "%s" TO "%s","%s"; + GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA "%s" TO "%s","%s","%s";` + connectionPoolerLookup = ` CREATE SCHEMA IF NOT EXISTS {{.pooler_schema}}; @@ -418,6 +425,19 @@ func (c *Cluster) execAlterGlobalDefaultPrivileges(owner, rolePrefix string) err return nil } +func (c *Cluster) execExtensionPostCreatePrivileges(schemaName, rolePrefix string) error { + if _, err := c.pgDb.Exec(fmt.Sprintf(extensionPostCreateSQL, + schemaName, rolePrefix+constants.OwnerRoleNameSuffix, rolePrefix+constants.ReaderRoleNameSuffix, // tables + schemaName, rolePrefix+constants.OwnerRoleNameSuffix, rolePrefix+constants.ReaderRoleNameSuffix, // sequences + schemaName, rolePrefix+constants.OwnerRoleNameSuffix, rolePrefix+constants.WriterRoleNameSuffix, // tables + schemaName, rolePrefix+constants.OwnerRoleNameSuffix, rolePrefix+constants.WriterRoleNameSuffix, // sequences + schemaName, rolePrefix+constants.OwnerRoleNameSuffix, rolePrefix+constants.ReaderRoleNameSuffix, rolePrefix+constants.WriterRoleNameSuffix)); err != nil { // functions + return fmt.Errorf("could not set privileges in schema %s: %v", schemaName, err) + } + + return nil +} + func makeUserFlags(rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin bool) (result []string) { if rolsuper { result = append(result, constants.RoleFlagSuperuser) @@ -484,22 +504,22 @@ func (c *Cluster) getExtensions() (dbExtensions map[string]string, err error) { // executeCreateExtension creates new extension in the given schema. // The caller is responsible for opening and closing the database connection. -func (c *Cluster) executeCreateExtension(extName, schemaName string) error { - return c.execCreateOrAlterExtension(extName, schemaName, createExtensionSQL, +func (c *Cluster) executeCreateExtension(extName, schemaName, schemaOwner string) error { + return c.execCreateOrAlterExtension(extName, schemaName, schemaOwner, createExtensionSQL, "creating extension", "create extension") } // executeAlterExtension changes the schema of the given extension. // The caller is responsible for opening and closing the database connection. -func (c *Cluster) executeAlterExtension(extName, schemaName string) error { - return c.execCreateOrAlterExtension(extName, schemaName, alterExtensionSQL, +func (c *Cluster) executeAlterExtension(extName, schemaName, schemaOwner string) error { + return c.execCreateOrAlterExtension(extName, schemaName, schemaOwner, alterExtensionSQL, "changing schema for extension", "alter extension schema") } -func (c *Cluster) execCreateOrAlterExtension(extName, schemaName, statement, doing, operation string) error { +func (c *Cluster) execCreateOrAlterExtension(extName, schemaName, schemaOwner, statement, doing, operation string) error { c.logger.Infof("%s %q schema %q", doing, extName, schemaName) - if _, err := c.pgDb.Exec(fmt.Sprintf(statement, extName, schemaName)); err != nil { + if _, err := c.pgDb.Exec(fmt.Sprintf(statement, schemaOwner, extName, schemaName)); err != nil { return fmt.Errorf("could not execute %s: %v", operation, err) } diff --git a/pkg/cluster/sync.go b/pkg/cluster/sync.go index 4937a2034..a1a062969 100644 --- a/pkg/cluster/sync.go +++ b/pkg/cluster/sync.go @@ -792,7 +792,7 @@ func (c *Cluster) syncPreparedDatabases() error { } // install extensions - if err := c.syncExtensions(preparedDB.Extensions); err != nil { + if err := c.syncExtensions(preparedDbName, preparedDB.Extensions); err != nil { return err } @@ -836,7 +836,7 @@ func (c *Cluster) syncPreparedSchemas(databaseName string, preparedSchemas map[s return nil } -func (c *Cluster) syncExtensions(extensions map[string]string) error { +func (c *Cluster) syncExtensions(databaseName string, extensions map[string]string) error { c.setProcessName("syncing database extensions") createExtensions := make(map[string]string) @@ -857,12 +857,20 @@ func (c *Cluster) syncExtensions(extensions map[string]string) error { } for extName, schema := range createExtensions { - if err = c.executeCreateExtension(extName, schema); err != nil { + if err = c.executeCreateExtension(extName, schema, databaseName+constants.OwnerRoleNameSuffix); err != nil { return err } + // grant privileges on objects created by the extension to default database roles + if err = c.execExtensionPostCreatePrivileges(schema, databaseName); err != nil { + return err + } + // try to grant to default schema roles, too, but defaultRoles could be false for schema + if err = c.execExtensionPostCreatePrivileges(schema, databaseName+"_"+schema); err != nil { + c.logger.Debugf("no privileges assigned to schema roles: %v", err) + } } for extName, schema := range alterExtensions { - if err = c.executeAlterExtension(extName, schema); err != nil { + if err = c.executeAlterExtension(extName, schema, databaseName+constants.OwnerRoleNameSuffix); err != nil { return err } }