Skip to content

Commit e28ea54

Browse files
[MISC] Sanitize PostgreSQL extra-user-roles arg (#876)
1 parent e92a015 commit e28ea54

File tree

4 files changed

+23
-11
lines changed

4 files changed

+23
-11
lines changed

lib/charms/postgresql_k8s/v0/postgresql.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
# Increment this PATCH version before using `charmcraft publish-lib` or reset
3737
# to 0 if you are raising the major API version
38-
LIBPATCH = 43
38+
LIBPATCH = 44
3939

4040
# Groups to distinguish database permissions
4141
PERMISSIONS_GROUP_ADMIN = "admin"
@@ -223,7 +223,7 @@ def create_user(
223223
user: str,
224224
password: Optional[str] = None,
225225
admin: bool = False,
226-
extra_user_roles: Optional[str] = None,
226+
extra_user_roles: Optional[list[str]] = None,
227227
) -> None:
228228
"""Creates a database user.
229229
@@ -238,7 +238,6 @@ def create_user(
238238
admin_role = False
239239
roles = privileges = None
240240
if extra_user_roles:
241-
extra_user_roles = tuple(extra_user_roles.lower().split(","))
242241
admin_role = PERMISSIONS_GROUP_ADMIN in extra_user_roles
243242
valid_privileges, valid_roles = self.list_valid_privileges_and_roles()
244243
roles = [
@@ -572,7 +571,7 @@ def set_up_database(self) -> None:
572571
)
573572
self.create_user(
574573
PERMISSIONS_GROUP_ADMIN,
575-
extra_user_roles="pg_read_all_data,pg_write_all_data",
574+
extra_user_roles=["pg_read_all_data", "pg_write_all_data"],
576575
)
577576
cursor.execute("GRANT CONNECT ON DATABASE postgres TO admin;")
578577
except psycopg2.Error as e:

src/charm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,7 @@ def _initialize_cluster(self, event: WorkloadEvent) -> bool:
10931093
self.postgresql.create_user(
10941094
MONITORING_USER,
10951095
self.get_secret(APP_SCOPE, MONITORING_PASSWORD_KEY),
1096-
extra_user_roles="pg_monitor",
1096+
extra_user_roles=["pg_monitor"],
10971097
)
10981098

10991099
self.postgresql.set_up_database()

src/relations/postgresql_provider.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ def __init__(self, charm: CharmBase, relation_name: str = "database") -> None:
6565
self.database_provides.on.database_requested, self._on_database_requested
6666
)
6767

68+
@staticmethod
69+
def _sanitize_extra_roles(extra_roles: str | None) -> list[str]:
70+
"""Standardize and sanitize user extra-roles."""
71+
if extra_roles is None:
72+
return []
73+
74+
return [role.lower() for role in extra_roles.split(",")]
75+
6876
def _on_database_requested(self, event: DatabaseRequestedEvent) -> None:
6977
"""Handle the legacy postgresql-client relation changed event.
7078
@@ -80,7 +88,9 @@ def _on_database_requested(self, event: DatabaseRequestedEvent) -> None:
8088

8189
# Retrieve the database name and extra user roles using the charm library.
8290
database = event.database
83-
extra_user_roles = event.extra_user_roles
91+
92+
# Make sure that certain groups are not in the list
93+
extra_user_roles = self._sanitize_extra_roles(event.extra_user_roles)
8494

8595
try:
8696
# Creates the user and the database for this specific relation.
@@ -268,9 +278,7 @@ def check_for_invalid_extra_user_roles(self, relation_id: int) -> bool:
268278
continue
269279
for data in relation.data.values():
270280
extra_user_roles = data.get("extra-user-roles")
271-
if extra_user_roles is None:
272-
continue
273-
extra_user_roles = extra_user_roles.lower().split(",")
281+
extra_user_roles = self._sanitize_extra_roles(extra_user_roles)
274282
for extra_user_role in extra_user_roles:
275283
if (
276284
extra_user_role not in valid_privileges

tests/unit/test_postgresql_provider.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,17 @@ def test_on_database_requested(harness):
107107
# Assert that the correct calls were made.
108108
user = f"relation_id_{rel_id}"
109109
postgresql_mock.create_user.assert_called_once_with(
110-
user, "test-password", extra_user_roles=EXTRA_USER_ROLES
110+
user,
111+
"test-password",
112+
extra_user_roles=[role.lower() for role in EXTRA_USER_ROLES.split(",")],
111113
)
112114
database_relation = harness.model.get_relation(RELATION_NAME)
113115
client_relations = [database_relation]
114116
postgresql_mock.create_database.assert_called_once_with(
115-
DATABASE, user, plugins=["pgaudit"], client_relations=client_relations
117+
DATABASE,
118+
user,
119+
plugins=["pgaudit"],
120+
client_relations=client_relations,
116121
)
117122
postgresql_mock.get_postgresql_version.assert_called_once()
118123

0 commit comments

Comments
 (0)