From 869502e721f81bcc3f630d90aedaa40a611ab1c3 Mon Sep 17 00:00:00 2001 From: Felix Kunde Date: Wed, 12 May 2021 11:53:14 +0200 Subject: [PATCH] deny LOGIN from deprecated roles --- e2e/tests/test_e2e.py | 28 +++++++++++++++------------- pkg/util/users/users.go | 15 ++++++++++++++- pkg/util/util.go | 13 +++++++++++++ 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/e2e/tests/test_e2e.py b/e2e/tests/test_e2e.py index 8c13a37db..8e371d73f 100644 --- a/e2e/tests/test_e2e.py +++ b/e2e/tests/test_e2e.py @@ -227,9 +227,9 @@ class EndToEndTestCase(unittest.TestCase): leader = self.k8s.get_cluster_leader_pod() user_query = """ - SELECT usename - FROM pg_catalog.pg_user - WHERE usename IN ('elephant', 'kind'); + SELECT rolname + FROM pg_catalog.pg_roles + WHERE rolname IN ('elephant', 'kind'); """ users = self.query_database(leader.metadata.name, "postgres", user_query) self.eventuallyEqual(lambda: len(users), 2, @@ -253,9 +253,10 @@ class EndToEndTestCase(unittest.TestCase): time.sleep(15) user_query = """ - SELECT usename - FROM pg_catalog.pg_user - WHERE usename IN ('tester', 'kind_delete_me'); + SELECT rolname + FROM pg_catalog.pg_roles + WHERE (rolname = 'tester' AND rolcanlogin) + OR (rolname = 'kind_delete_me' AND NOT rolcanlogin); """ users = self.query_database(leader.metadata.name, "postgres", user_query) self.eventuallyEqual(lambda: len(users), 2, @@ -279,9 +280,10 @@ class EndToEndTestCase(unittest.TestCase): time.sleep(15) user_query = """ - SELECT usename - FROM pg_catalog.pg_user - WHERE usename IN ('tester_delete_me', 'kind'); + SELECT rolname + FROM pg_catalog.pg_roles + WHERE (rolname = 'kind' AND rolcanlogin) + OR (rolname = 'tester_delete_me' AND NOT rolcanlogin); """ users = self.query_database(leader.metadata.name, "postgres", user_query) self.eventuallyEqual(lambda: len(users), 2, @@ -459,9 +461,9 @@ class EndToEndTestCase(unittest.TestCase): leader = k8s.get_cluster_leader_pod() schemas_query = """ - select schema_name - from information_schema.schemata - where schema_name = 'pooler' + SELECT schema_name + FROM information_schema.schemata + WHERE schema_name = 'pooler' """ db_list = self.list_databases(leader.metadata.name) @@ -1470,7 +1472,7 @@ class EndToEndTestCase(unittest.TestCase): k8s = self.k8s result_set = [] db_list = [] - db_list_query = "select datname from pg_database" + db_list_query = "SELECT datname FROM pg_database" exec_query = r"psql -tAq -c \"{}\" -d {}" try: diff --git a/pkg/util/users/users.go b/pkg/util/users/users.go index 63f230ce5..e81ddd119 100644 --- a/pkg/util/users/users.go +++ b/pkg/util/users/users.go @@ -9,6 +9,7 @@ import ( "github.com/zalando/postgres-operator/pkg/spec" "github.com/zalando/postgres-operator/pkg/util" + "github.com/zalando/postgres-operator/pkg/util/constants" ) const ( @@ -75,9 +76,21 @@ func (strategy DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserM } // No existing roles are deleted or stripped of role membership/flags - // but they will be renamed acting as a simple login blocker + // but team roles will be renamed and denied from LOGIN for name, dbUser := range dbUsers { if _, exists := newUsers[name]; !exists { + // toggle LOGIN flag based on role deprecation + userFlags := make([]string, len(dbUser.Flags)) + userFlags = append(userFlags, dbUser.Flags...) + if dbUser.Deprecated { + util.StringSliceReplaceElement(&dbUser.Flags, constants.RoleFlagNoLogin, constants.RoleFlagLogin) + } else { + util.StringSliceReplaceElement(&dbUser.Flags, constants.RoleFlagLogin, constants.RoleFlagNoLogin) + } + if !util.IsEqualIgnoreOrder(userFlags, dbUser.Flags) { + reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGsyncUserAlter, User: dbUser}) + } + reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGSyncUserRename, User: dbUser}) } } diff --git a/pkg/util/util.go b/pkg/util/util.go index bebb9f8da..18ee717d0 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -151,6 +151,19 @@ func IsEqualIgnoreOrder(a, b []string) bool { return reflect.DeepEqual(a_copy, b_copy) } +// SliceReplaceElement +func StringSliceReplaceElement(s *[]string, a, b string) *[]string { + tmp := *s + for _, str := range tmp { + if str == a { + str = b + } + tmp = append(tmp, str) + } + *s = tmp + return s +} + // SubstractStringSlices finds elements in a that are not in b and return them as a result slice. func SubstractStringSlices(a []string, b []string) (result []string, equal bool) { // Slices are assumed to contain unique elements only