Allow global configuration options for API roles.
Add options to the PgUser structure, potentially allowing to set per-role options in the cluster definition as well. Introduce api_roles_configuration operator option with the default of log_statement=all
This commit is contained in:
parent
6dcd074ea0
commit
415a7fdc4d
|
|
@ -39,3 +39,4 @@ data:
|
||||||
pod_terminate_grace_period: 5m
|
pod_terminate_grace_period: 5m
|
||||||
pdb_name_format: "postgres-{cluster}-pdb"
|
pdb_name_format: "postgres-{cluster}-pdb"
|
||||||
eol_node_label: "eol:true"
|
eol_node_label: "eol:true"
|
||||||
|
api_roles_configuration: "log_statement:all"
|
||||||
|
|
|
||||||
|
|
@ -645,7 +645,12 @@ func (c *Cluster) initHumanUsers() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.pgUsers[username] = spec.PgUser{Name: username, Flags: flags, MemberOf: memberOf}
|
c.pgUsers[username] = spec.PgUser{
|
||||||
|
Name: username,
|
||||||
|
Flags: flags,
|
||||||
|
MemberOf: memberOf,
|
||||||
|
Parameters: c.OpConfig.APIRolesParameters,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -359,7 +359,11 @@ func (c *Cluster) syncRoles(readFromDatabase bool) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not init db connection: %v", err)
|
return fmt.Errorf("could not init db connection: %v", err)
|
||||||
}
|
}
|
||||||
defer c.closeDbConn()
|
defer func() {
|
||||||
|
if err := c.closeDbConn(); err != nil {
|
||||||
|
c.logger.Errorf("could not close db connection: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if readFromDatabase {
|
if readFromDatabase {
|
||||||
for _, u := range c.pgUsers {
|
for _, u := range c.pgUsers {
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ type syncUserOperation int
|
||||||
const (
|
const (
|
||||||
PGSyncUserAdd = iota
|
PGSyncUserAdd = iota
|
||||||
PGsyncUserAlter
|
PGsyncUserAlter
|
||||||
|
PGSyncAlterSet // handle ALTER ROLE SET parameter = value
|
||||||
)
|
)
|
||||||
|
|
||||||
// PodEvent describes the event for a single Pod
|
// PodEvent describes the event for a single Pod
|
||||||
|
|
@ -61,6 +62,7 @@ type PgUser struct {
|
||||||
Password string
|
Password string
|
||||||
Flags []string
|
Flags []string
|
||||||
MemberOf []string
|
MemberOf []string
|
||||||
|
Parameters map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// PgUserMap maps user names to the definitions.
|
// PgUserMap maps user names to the definitions.
|
||||||
|
|
|
||||||
|
|
@ -65,12 +65,13 @@ type Config struct {
|
||||||
TeamAdminRole string `name:"team_admin_role" default:"admin"`
|
TeamAdminRole string `name:"team_admin_role" default:"admin"`
|
||||||
EnableLoadBalancer bool `name:"enable_load_balancer" default:"true"`
|
EnableLoadBalancer bool `name:"enable_load_balancer" default:"true"`
|
||||||
MasterDNSNameFormat stringTemplate `name:"master_dns_name_format" default:"{cluster}.{team}.{hostedzone}"`
|
MasterDNSNameFormat stringTemplate `name:"master_dns_name_format" default:"{cluster}.{team}.{hostedzone}"`
|
||||||
ReplicaDNSNameFormat stringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{team}.{hostedzone}"`
|
ReplicaDNSNameFormat stringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{team}.{hostedzone}"`
|
||||||
PDBNameFormat stringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"`
|
PDBNameFormat stringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"`
|
||||||
Workers uint32 `name:"workers" default:"4"`
|
Workers uint32 `name:"workers" default:"4"`
|
||||||
APIPort int `name:"api_port" default:"8080"`
|
APIPort int `name:"api_port" default:"8080"`
|
||||||
RingLogLines int `name:"ring_log_lines" default:"100"`
|
RingLogLines int `name:"ring_log_lines" default:"100"`
|
||||||
ClusterHistoryEntries int `name:"cluster_history_entries" default:"1000"`
|
ClusterHistoryEntries int `name:"cluster_history_entries" default:"1000"`
|
||||||
|
APIRolesParameters map[string]string `name:"api_roles_configuration" default:"log_statement:all"`
|
||||||
|
|
||||||
PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"`
|
PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,14 @@ import (
|
||||||
|
|
||||||
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
||||||
"github.com/zalando-incubator/postgres-operator/pkg/util"
|
"github.com/zalando-incubator/postgres-operator/pkg/util"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
createUserSQL = `SET LOCAL synchronous_commit = 'local'; CREATE ROLE "%s" %s %s;`
|
createUserSQL = `SET LOCAL synchronous_commit = 'local'; CREATE ROLE "%s" %s %s;`
|
||||||
alterUserSQL = `ALTER ROLE "%s" %s`
|
alterUserSQL = `ALTER ROLE "%s" %s`
|
||||||
|
alterRoleResetAllSQL = `ALTER ROLE "%s" RESET ALL`
|
||||||
|
alterRoleSetSQL = `ALTER ROLE "%s" SET "%s" TO "%s"`
|
||||||
grantToUserSQL = `GRANT %s TO "%s"`
|
grantToUserSQL = `GRANT %s TO "%s"`
|
||||||
doBlockStmt = `SET LOCAL synchronous_commit = 'local'; DO $$ BEGIN %s; END;$$;`
|
doBlockStmt = `SET LOCAL synchronous_commit = 'local'; DO $$ BEGIN %s; END;$$;`
|
||||||
passwordTemplate = "ENCRYPTED PASSWORD '%s'"
|
passwordTemplate = "ENCRYPTED PASSWORD '%s'"
|
||||||
|
|
@ -34,6 +37,9 @@ func (s DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserMap,
|
||||||
dbUser, exists := dbUsers[name]
|
dbUser, exists := dbUsers[name]
|
||||||
if !exists {
|
if !exists {
|
||||||
reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGSyncUserAdd, User: newUser})
|
reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGSyncUserAdd, User: newUser})
|
||||||
|
if len(newUser.Parameters) > 0 {
|
||||||
|
reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGSyncAlterSet, User: newUser})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
r := spec.PgSyncUserRequest{}
|
r := spec.PgSyncUserRequest{}
|
||||||
newMD5Password := util.PGUserPassword(newUser)
|
newMD5Password := util.PGUserPassword(newUser)
|
||||||
|
|
@ -54,6 +60,9 @@ func (s DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserMap,
|
||||||
r.User.Name = newUser.Name
|
r.User.Name = newUser.Name
|
||||||
reqs = append(reqs, r)
|
reqs = append(reqs, r)
|
||||||
}
|
}
|
||||||
|
if !reflect.DeepEqual(dbUser.Parameters, newUser.Parameters) {
|
||||||
|
reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGSyncAlterSet, User: newUser})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,6 +81,10 @@ func (s DefaultUserSyncStrategy) ExecuteSyncRequests(reqs []spec.PgSyncUserReque
|
||||||
if err := s.alterPgUser(r.User, db); err != nil {
|
if err := s.alterPgUser(r.User, db); err != nil {
|
||||||
return fmt.Errorf("could not alter user %q: %v", r.User.Name, err)
|
return fmt.Errorf("could not alter user %q: %v", r.User.Name, err)
|
||||||
}
|
}
|
||||||
|
case spec.PGSyncAlterSet:
|
||||||
|
if err := s.alterPgUserSet(r.User, db); err != nil {
|
||||||
|
return fmt.Errorf("could not set custom user %q parameters: %v", r.User.Name, err)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unrecognized operation: %v", r.Kind)
|
return fmt.Errorf("unrecognized operation: %v", r.Kind)
|
||||||
}
|
}
|
||||||
|
|
@ -79,6 +92,15 @@ func (s DefaultUserSyncStrategy) ExecuteSyncRequests(reqs []spec.PgSyncUserReque
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (strategy DefaultUserSyncStrategy) alterPgUserSet(user spec.PgUser, db *sql.DB) (err error) {
|
||||||
|
queries := produceAlterRoleSetStmts(user)
|
||||||
|
query := fmt.Sprintf(doBlockStmt, strings.Join(queries, ";"))
|
||||||
|
if _, err = db.Query(query); err != nil {
|
||||||
|
err = fmt.Errorf("dB error: %v, query: %q", err, query)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (s DefaultUserSyncStrategy) createPgUser(user spec.PgUser, db *sql.DB) (err error) {
|
func (s DefaultUserSyncStrategy) createPgUser(user spec.PgUser, db *sql.DB) (err error) {
|
||||||
var userFlags []string
|
var userFlags []string
|
||||||
|
|
@ -148,6 +170,15 @@ func produceAlterStmt(user spec.PgUser) string {
|
||||||
return fmt.Sprintf(alterUserSQL, user.Name, strings.Join(result, " "))
|
return fmt.Sprintf(alterUserSQL, user.Name, strings.Join(result, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func produceAlterRoleSetStmts(user spec.PgUser) []string {
|
||||||
|
result := make([]string, 1)
|
||||||
|
result = append(result, fmt.Sprintf(alterRoleResetAllSQL, user.Name))
|
||||||
|
for key, value := range(user.Parameters) {
|
||||||
|
result = append(result, fmt.Sprintf(alterRoleSetSQL, user.Name, key, value))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func produceGrantStmt(user spec.PgUser) string {
|
func produceGrantStmt(user spec.PgUser) string {
|
||||||
// GRANT ROLE "foo", "bar" TO baz
|
// GRANT ROLE "foo", "bar" TO baz
|
||||||
return fmt.Sprintf(grantToUserSQL, quoteMemberList(user), user.Name)
|
return fmt.Sprintf(grantToUserSQL, quoteMemberList(user), user.Name)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue