canonical / canonical/postgresql-single-kernel-library

feat(database): accept GROUP entity requests from data-integrator to provision mapped authorization groups

Open
#297 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
4
Forks
3
Avg merge
3d 17h
Merged PRs (30d)
26

Description

### Description

Per the DA148 LDAP integration spec, PostgreSQL LDAP (identity) users get their authorization through group membership: the `ldap_map` config option maps LDAP groups to pre-created PostgreSQL group roles, and the `ldap-sync` sidecar grants synced users membership in the mapped role. The charm itself grants no database privileges to identity users — `identity_access` is a pure authentication marker (hba `ldap` line), by design (least privilege).

Today, the operator must therefore perform a manual `GRANT` after setting up the mapping:

```sql
CREATE ROLE NOLOGIN;
GRANT CONNECT ON DATABASE TO ;
```

This works, but the operator must know the mapping up front and run DDL by hand, and there is a foot-gun: `validate_group_map` accepts *any* existing role as a mapping target, including charm-managed LOGIN users (`relation_id_N`, system users).

### Suggested improvement

Support the GROUP entity protocol that `data_platform_libs` (vendored `data_interfaces.py`, `LIBAPI 0`) and `data-integrator` already implement on the requirer side:

- data-integrator exposes `entity-type=GROUP`, `extra-group-roles`, and `entity-permissions` (`[{"resource_name": ..., "resource_type": ..., "privileges": [...]}]`), and sends them in the relation application data.
- The PostgreSQL provider currently ignores them: `DatabaseRequestedEvent` exposes only `extra_user_roles` / `requested_entity_secret_content`, and `managers/database.py` unconditionally creates a LOGIN relation user.

### Proposed change (provider side)

1. `DatabaseRequestedEvent` (vendored `data_interfaces.py`): expose `entity_type`, `extra_group_roles`, and `entity_permissions` properties (read from the relation application data, mirroring the requirer-side fields).
2. `managers/database.py`: carry the fields in `DatabaseRequest`; on `entity_type == GROUP` create a NOLOGIN group role (no credentials/secret, no relation-access mixing) named e.g. `group_` and apply the requested `entity_permissions` on the requested database(s); skip the credential flow; write the resulting group name back into the relation data.
3. Hardening: reject mapping targets in `validate_group_map` that are charm-managed LOGIN users (`relation_id_%`, system users), so `ldap-map` cannot silently pour LDAP users into a client charm's LOGIN role (breaks per-user identity/auditing, and the mapping dangles if the relation is re-created).

### Resulting UX

```
juju config data-integrator entity-type=GROUP entity-permissions='[{"resource_name": "mydb", "resource_type": "database", "privileges": ["CONNECT"]}]'
juju config postgresql ldap-map=superheros=group_0 # group exists once the request is processed
```

No operator DDL: synced LDAP users inherit the group's privileges.

### Scope note

The LDAP integration test PRs (#1723 K8s / #1936 VM) currently keep the explicit operator grant and document this limitation; once this lands they can switch to the group-request flow and drop the grant.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the GROUP entity fields in the vendored data_interfaces.py and the existing DatabaseRequestedEvent flow, then trace DatabaseRequest and role handling in managers/database.py. Review validate_group_map for charm-managed LOGIN targets. Done means GROUP requests create a NOLOGIN role, apply entity_permissions, avoid credentials, and publish the group name back through the relation data.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql, python
Domain
authorization, backend-api-design, databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.