Skip to content

Commit 9ee14f2

Browse files
authored
let isSystemUsername check all system users (#2489)
* let isSystemUsername check all system users * extend robot user unit test * reset system users for initSystemUser test
1 parent 96077c4 commit 9ee14f2

File tree

2 files changed

+81
-21
lines changed

2 files changed

+81
-21
lines changed

pkg/cluster/cluster_test.go

Lines changed: 73 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
const (
2727
superUserName = "postgres"
2828
replicationUserName = "standby"
29+
poolerUserName = "pooler"
30+
adminUserName = "admin"
2931
exampleSpiloConfig = `{"postgresql":{"bin_dir":"/usr/lib/postgresql/12/bin","parameters":{"autovacuum_analyze_scale_factor":"0.1"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"test":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"postgresql":{"parameters":{"max_connections":"100","max_locks_per_transaction":"64","max_worker_processes":"4"}}}}}`
3032
spiloConfigDiff = `{"postgresql":{"bin_dir":"/usr/lib/postgresql/12/bin","parameters":{"autovacuum_analyze_scale_factor":"0.1"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"test":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"postgresql":{"parameters":{"max_locks_per_transaction":"64","max_worker_processes":"4"}}}}}`
3133
)
@@ -37,7 +39,7 @@ var cl = New(
3739
Config{
3840
OpConfig: config.Config{
3941
PodManagementPolicy: "ordered_ready",
40-
ProtectedRoles: []string{"admin", "cron_admin", "part_man"},
42+
ProtectedRoles: []string{adminUserName, "cron_admin", "part_man"},
4143
Auth: config.Auth{
4244
SuperUsername: superUserName,
4345
ReplicationUsername: replicationUserName,
@@ -46,6 +48,9 @@ var cl = New(
4648
Resources: config.Resources{
4749
DownscalerAnnotations: []string{"downscaler/*"},
4850
},
51+
ConnectionPooler: config.ConnectionPooler{
52+
User: poolerUserName,
53+
},
4954
},
5055
},
5156
k8sutil.NewMockKubernetesClient(),
@@ -55,6 +60,20 @@ var cl = New(
5560
Namespace: "test",
5661
Annotations: map[string]string{"downscaler/downtime_replicas": "0"},
5762
},
63+
Spec: acidv1.PostgresSpec{
64+
EnableConnectionPooler: util.True(),
65+
Streams: []acidv1.Stream{
66+
acidv1.Stream{
67+
ApplicationId: "test-app",
68+
Database: "test_db",
69+
Tables: map[string]acidv1.StreamTable{
70+
"test_table": acidv1.StreamTable{
71+
EventType: "test-app.test",
72+
},
73+
},
74+
},
75+
},
76+
},
5877
},
5978
logger,
6079
eventRecorder,
@@ -127,56 +146,85 @@ func TestStatefulSetUpdateWithEnv(t *testing.T) {
127146

128147
func TestInitRobotUsers(t *testing.T) {
129148
tests := []struct {
149+
testCase string
130150
manifestUsers map[string]acidv1.UserFlags
131151
infraRoles map[string]spec.PgUser
132152
result map[string]spec.PgUser
133153
err error
134154
}{
135155
{
156+
testCase: "manifest user called like infrastructure role - latter should take percedence",
136157
manifestUsers: map[string]acidv1.UserFlags{"foo": {"superuser", "createdb"}},
137158
infraRoles: map[string]spec.PgUser{"foo": {Origin: spec.RoleOriginInfrastructure, Name: "foo", Namespace: cl.Namespace, Password: "bar"}},
138159
result: map[string]spec.PgUser{"foo": {Origin: spec.RoleOriginInfrastructure, Name: "foo", Namespace: cl.Namespace, Password: "bar"}},
139160
err: nil,
140161
},
141162
{
163+
testCase: "manifest user with forbidden characters",
142164
manifestUsers: map[string]acidv1.UserFlags{"!fooBar": {"superuser", "createdb"}},
143165
err: fmt.Errorf(`invalid username: "!fooBar"`),
144166
},
145167
{
168+
testCase: "manifest user with unknown privileges (should be catched by CRD, too)",
146169
manifestUsers: map[string]acidv1.UserFlags{"foobar": {"!superuser", "createdb"}},
147170
err: fmt.Errorf(`invalid flags for user "foobar": ` +
148171
`user flag "!superuser" is not alphanumeric`),
149172
},
150173
{
174+
testCase: "manifest user with unknown privileges - part 2 (should be catched by CRD, too)",
151175
manifestUsers: map[string]acidv1.UserFlags{"foobar": {"superuser1", "createdb"}},
152176
err: fmt.Errorf(`invalid flags for user "foobar": ` +
153177
`user flag "SUPERUSER1" is not valid`),
154178
},
155179
{
180+
testCase: "manifest user with conflicting flags",
156181
manifestUsers: map[string]acidv1.UserFlags{"foobar": {"inherit", "noinherit"}},
157182
err: fmt.Errorf(`invalid flags for user "foobar": ` +
158183
`conflicting user flags: "NOINHERIT" and "INHERIT"`),
159184
},
160185
{
161-
manifestUsers: map[string]acidv1.UserFlags{"admin": {"superuser"}, superUserName: {"createdb"}},
186+
testCase: "manifest user called like Spilo system users",
187+
manifestUsers: map[string]acidv1.UserFlags{superUserName: {"createdb"}, replicationUserName: {"replication"}},
188+
infraRoles: map[string]spec.PgUser{},
189+
result: map[string]spec.PgUser{},
190+
err: nil,
191+
},
192+
{
193+
testCase: "manifest user called like protected user name",
194+
manifestUsers: map[string]acidv1.UserFlags{adminUserName: {"superuser"}},
195+
infraRoles: map[string]spec.PgUser{},
196+
result: map[string]spec.PgUser{},
197+
err: nil,
198+
},
199+
{
200+
testCase: "manifest user called like pooler system user",
201+
manifestUsers: map[string]acidv1.UserFlags{poolerUserName: {}},
202+
infraRoles: map[string]spec.PgUser{},
203+
result: map[string]spec.PgUser{},
204+
err: nil,
205+
},
206+
{
207+
testCase: "manifest user called like stream system user",
208+
manifestUsers: map[string]acidv1.UserFlags{"fes_user": {"replication"}},
162209
infraRoles: map[string]spec.PgUser{},
163210
result: map[string]spec.PgUser{},
164211
err: nil,
165212
},
166213
}
214+
cl.initSystemUsers()
167215
for _, tt := range tests {
168216
cl.Spec.Users = tt.manifestUsers
169217
cl.pgUsers = tt.infraRoles
170218
if err := cl.initRobotUsers(); err != nil {
171219
if tt.err == nil {
172-
t.Errorf("%s got an unexpected error: %v", t.Name(), err)
220+
t.Errorf("%s - %s: got an unexpected error: %v", tt.testCase, t.Name(), err)
173221
}
174222
if err.Error() != tt.err.Error() {
175-
t.Errorf("%s expected error %v, got %v", t.Name(), tt.err, err)
223+
t.Errorf("%s - %s: expected error %v, got %v", tt.testCase, t.Name(), tt.err, err)
176224
}
177225
} else {
178226
if !reflect.DeepEqual(cl.pgUsers, tt.result) {
179-
t.Errorf("%s expected: %#v, got %#v", t.Name(), tt.result, cl.pgUsers)
227+
t.Errorf("%s - %s: expected: %#v, got %#v", tt.testCase, t.Name(), tt.result, cl.pgUsers)
180228
}
181229
}
182230
}
@@ -269,7 +317,7 @@ func TestInitHumanUsers(t *testing.T) {
269317
},
270318
{
271319
existingRoles: map[string]spec.PgUser{},
272-
teamRoles: []string{"admin", replicationUserName},
320+
teamRoles: []string{adminUserName, replicationUserName},
273321
result: map[string]spec.PgUser{},
274322
err: nil,
275323
},
@@ -896,6 +944,11 @@ func TestServiceAnnotations(t *testing.T) {
896944
}
897945

898946
func TestInitSystemUsers(t *testing.T) {
947+
// reset system users, pooler and stream section
948+
cl.systemUsers = make(map[string]spec.PgUser)
949+
cl.Spec.EnableConnectionPooler = boolToPointer(false)
950+
cl.Spec.Streams = []acidv1.Stream{}
951+
899952
// default cluster without connection pooler and event streams
900953
cl.initSystemUsers()
901954
if _, exist := cl.systemUsers[constants.ConnectionPoolerUserKeyName]; exist {
@@ -914,35 +967,35 @@ func TestInitSystemUsers(t *testing.T) {
914967

915968
// superuser is not allowed as connection pool user
916969
cl.Spec.ConnectionPooler = &acidv1.ConnectionPooler{
917-
User: "postgres",
970+
User: superUserName,
918971
}
919-
cl.OpConfig.SuperUsername = "postgres"
920-
cl.OpConfig.ConnectionPooler.User = "pooler"
972+
cl.OpConfig.SuperUsername = superUserName
973+
cl.OpConfig.ConnectionPooler.User = poolerUserName
921974

922975
cl.initSystemUsers()
923-
if _, exist := cl.systemUsers["pooler"]; !exist {
976+
if _, exist := cl.systemUsers[poolerUserName]; !exist {
924977
t.Errorf("%s, Superuser is not allowed to be a connection pool user", t.Name())
925978
}
926979

927980
// neither protected users are
928-
delete(cl.systemUsers, "pooler")
981+
delete(cl.systemUsers, poolerUserName)
929982
cl.Spec.ConnectionPooler = &acidv1.ConnectionPooler{
930-
User: "admin",
983+
User: adminUserName,
931984
}
932-
cl.OpConfig.ProtectedRoles = []string{"admin"}
985+
cl.OpConfig.ProtectedRoles = []string{adminUserName}
933986

934987
cl.initSystemUsers()
935-
if _, exist := cl.systemUsers["pooler"]; !exist {
988+
if _, exist := cl.systemUsers[poolerUserName]; !exist {
936989
t.Errorf("%s, Protected user are not allowed to be a connection pool user", t.Name())
937990
}
938991

939-
delete(cl.systemUsers, "pooler")
992+
delete(cl.systemUsers, poolerUserName)
940993
cl.Spec.ConnectionPooler = &acidv1.ConnectionPooler{
941-
User: "standby",
994+
User: replicationUserName,
942995
}
943996

944997
cl.initSystemUsers()
945-
if _, exist := cl.systemUsers["pooler"]; !exist {
998+
if _, exist := cl.systemUsers[poolerUserName]; !exist {
946999
t.Errorf("%s, System users are not allowed to be a connection pool user", t.Name())
9471000
}
9481001

@@ -960,8 +1013,8 @@ func TestInitSystemUsers(t *testing.T) {
9601013
ApplicationId: "test-app",
9611014
Database: "test_db",
9621015
Tables: map[string]acidv1.StreamTable{
963-
"data.test_table": {
964-
EventType: "test_event",
1016+
"test_table": {
1017+
EventType: "test-app.test",
9651018
},
9661019
},
9671020
},
@@ -1017,7 +1070,7 @@ func TestPreparedDatabases(t *testing.T) {
10171070
subTest: "Test admin role of owner",
10181071
role: "foo_owner",
10191072
memberOf: "",
1020-
admin: "admin",
1073+
admin: adminUserName,
10211074
},
10221075
{
10231076
subTest: "Test writer is a member of reader",

pkg/cluster/util.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,14 @@ func (c *Cluster) isProtectedUsername(username string) bool {
7878
}
7979

8080
func (c *Cluster) isSystemUsername(username string) bool {
81-
return (username == c.OpConfig.SuperUsername || username == c.OpConfig.ReplicationUsername)
81+
// is there a pooler system user defined
82+
for _, systemUser := range c.systemUsers {
83+
if username == systemUser.Name {
84+
return true
85+
}
86+
}
87+
88+
return false
8289
}
8390

8491
func isValidFlag(flag string) bool {

0 commit comments

Comments
 (0)