Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/.custom_wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ cjk
codebase
config
configs
CREATEDB
cryptographically
CSR
CSRs
Expand Down
66 changes: 26 additions & 40 deletions docs/explanation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,40 @@
Additional context about key concepts behind the PostgreSQL charm, including design and legacy information.

## Core concepts and design
* [Architecture]
* [Interfaces and endpoints]
* [Juju]
* [Legacy charm]

## Operational concepts
* [Users]
* [Logs]
* [Connection pooling]

## Security and hardening
* [Security hardening guide][Security]
* [Cryptography]

## Development
Charm event flowcharts:
* [Charm]
* [Relations]
* [Backups]

<!-- Links -->

[Architecture]: /explanation/architecture
[Interfaces and endpoints]: /explanation/interfaces-and-endpoints
[Users]: /explanation/users
[Logs]: /explanation/logs
[Juju]: /explanation/juju
[Legacy charm]: /explanation/legacy-charm
[Connection pooling]: /explanation/connection-pooling
[Charm]: /explanation/flowcharts/charm
[Relations]: /explanation/flowcharts/relations
[Backups]: /explanation/flowcharts/backups
[Security]: /explanation/security/index
[Cryptography]: /explanation/security/cryptography


```{toctree}
:titlesonly:
:maxdepth: 2
:glob:
:hidden:

Architecture <architecture>
Interfaces and endpoints <interfaces-and-endpoints>
Juju <juju>
Legacy charm <legacy-charm>
```

## Operational concepts

```{toctree}
:titlesonly:

Users <users>
Roles <roles>
Logs <logs>
Connection pooling <connection-pooling>
Security <security/index>
Flowcharts <flowcharts/index>
```

## Security and hardening

```{toctree}
:titlesonly:
:includehidden:

Security hardening guide: <security/index>
```

## Development

```{toctree}
:titlesonly:

Charm event flowcharts: <flowcharts/index>
```
4 changes: 2 additions & 2 deletions docs/explanation/legacy-charm.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

There are [two types of charms](https://documentation.ubuntu.com/juju/3.6/reference/charm/#by-generation) stored under the same charm name `postgresql-k8s`:

1. [Reactive](https://documentation.ubuntu.com/juju/3.6/reference/charm/#reactive) charm in the channel `latest/stable` (called `legacy`)
2. [Ops-based](https://documentation.ubuntu.com/juju/3.6/reference/charm/#ops) charm in the channel `14/stable` (called `modern`)
1. [Reactive](https://documentation.ubuntu.com/juju/3.6/reference/charm/#reactive-charm) charm in the channel `latest/stable` (called `legacy`)
2. [Ops-based](https://documentation.ubuntu.com/juju/3.6/reference/charm/#ops-charm) charm in the channel `14/stable` (called `modern`)

The legacy charm provided endpoints `db` and `db-admin` (for the interface `pgsql`). The modern charm provides old endpoints as well + new endpoint `database` (for the interface `postgresql_client`). Read more details about the available [endpoints/interfaces](/explanation/interfaces-and-endpoints).

Expand Down
197 changes: 197 additions & 0 deletions docs/explanation/roles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# Roles

There are several definitions of roles in Charmed PostgreSQL:
* Predefined PostgreSQL roles
* Instance-level DB/relation-specific roles
* LDAP-specific roles
* Extra user roles relation flag

```{seealso}
For details on how users relate to roles, see [](/explanation/users).
```

## PostgreSQL 16 roles

```text
test123=> SELECT * FROM pg_roles;
rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolbypassrls | rolconfig | oid
-----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+-------------+---------------+--------------+-----------+-------
pg_database_owner | f | t | f | f | f | f | -1 | ******** | | f | | 6171
pg_read_all_data | f | t | f | f | f | f | -1 | ******** | | f | | 6181
pg_write_all_data | f | t | f | f | f | f | -1 | ******** | | f | | 6182
pg_monitor | f | t | f | f | f | f | -1 | ******** | | f | | 3373
pg_read_all_settings | f | t | f | f | f | f | -1 | ******** | | f | | 3374
pg_read_all_stats | f | t | f | f | f | f | -1 | ******** | | f | | 3375
pg_stat_scan_tables | f | t | f | f | f | f | -1 | ******** | | f | | 3377
pg_read_server_files | f | t | f | f | f | f | -1 | ******** | | f | | 4569
pg_write_server_files | f | t | f | f | f | f | -1 | ******** | | f | | 4570
pg_execute_server_program | f | t | f | f | f | f | -1 | ******** | | f | | 4571
pg_signal_backend | f | t | f | f | f | f | -1 | ******** | | f | | 4200
pg_checkpoint | f | t | f | f | f | f | -1 | ******** | | f | | 4544
pg_use_reserved_connections | f | t | f | f | f | f | -1 | ******** | | f | | 4550
pg_create_subscription | f | t | f | f | f | f | -1 | ******** | | f | | 6304
...
```

## Charmed PostgreSQL 16 roles

Charmed PostgreSQL 16 introduces the following instance-level predefined roles:

* `charmed_stats` (inherit from pg_monitor)
* `charmed_read` (inherit from pg_read_all_data and `charmed_stats`)
* `charmed_dml` (inherit from pg_write_all_data and `charmed_read`)
* `charmed_backup` (inherit from pg_checkpoint and `charmed_stats`)
* `charmed_dba` (allowed to escalate to any other user, including the superuser `operator`)
* `charmed_admin` (inherit from `charmed_dml` and allowed to escalate to the database-specific `charmed_<database-name>_owner` role, which is explained later in this document)
* `charmed_databases_owner` (allowed to create databases; it can be requested through the CREATEDB extra user role)

Currently, `charmed_backup` and `charmed_dba` cannot be requested through the relation as extra user roles.

```text
test123=> SELECT * FROM pg_roles;
rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolbypassrls | rolconfig | oid
-----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+-------------+---------------+--------------+-----------+-------
...
charmed_stats | f | t | f | f | f | f | -1 | ******** | | f | | 16386
charmed_read | f | t | f | f | f | f | -1 | ******** | | f | | 16388
charmed_dml | f | t | f | f | f | f | -1 | ******** | | f | | 16390
charmed_backup | f | t | f | f | f | f | -1 | ******** | | f | | 16392
charmed_dba | f | t | f | f | f | f | -1 | ******** | | f | | 16393
charmed_admin | f | t | f | f | f | f | -1 | ******** | | f | | 16394
charmed_databases_owner | f | t | f | t | t | f | -1 | ******** | | f | | 16395
...
```

Charmed PostgreSQL 16 also introduces catalogue/database level roles, with permissions tied to each database that's created. Example for a database named `test`:

```text
test123=> SELECT * FROM pg_roles WHERE rolname LIKE 'charmed_test_%';
rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolbypassrls | rolconfig | oid
--------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+-------------+---------------+--------------+-----------+-------
charmed_test_owner | f | t | f | f | f | f | -1 | ******** | | f | | 16396
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when I request database databases, re: charmed_databases_owner in line 61?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The charm will throw an error. I'm currently working on fixing that. Thanks for catching this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed on canonical/postgresql-single-kernel-library#18 (there are two follow-up PRs in the operators repositories).

charmed_test_admin | f | f | f | f | f | f | -1 | ******** | | f | | 16397
charmed_test_dml | f | t | f | f | f | f | -1 | ******** | | f | | 16398
```

The `charmed_<database-name>_admin` role is assigned to each relation user (explained in the next section) with access to the specific database. When that user connects to the database, it's auto-escalated to the `charmed_<database-name>_owner` user, which will own every object inside the database, simplifying the permissions to perform operations on those objects when a new user requests access to that same database.

There is also a `charmed_<database-name>_dml` role that is assigned to each relation user to still allow them to read and write to the database objects even if the mechanism to auto-escalate the relation user to the `charmed_<database-name>_owner` role doesn't work.

### Relation-specific roles

For each application/relation, the dedicated user has been created:

```text
postgres=# SELECT * FROM pg_roles;
rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolbypassrls | rolconfig | oid
----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+-------------+---------------+--------------+-----------+-------
...
relation_id_12 | f | t | t | t | t | f | -1 | ******** | | f | | 16416
...

postgres=# SELECT * FROM pg_user;
usename | usesysid | usecreatedb | usesuper | userepl | usebypassrls | passwd | valuntil | useconfig
----------------------------+----------+-------------+----------+---------+--------------+----------+----------+-----------
...
relation_id_12 | 16416 | t | f | f | f | ******** | |
```

When the same application is being related through PgBouncer, the extra users/roles are created following the same logic as above:

```text
postgres=# SELECT * FROM pg_roles;
rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolbypassrls | rolconfig | oid
----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+-------------+---------------+--------------+-----------+-------
...
relation-14 | t | t | f | f | t | f | -1 | ******** | | f | | 16403
pgbouncer_auth_relation_14 | t | t | f | f | t | f | -1 | ******** | | f | | 16410
relation_id_13 | f | t | t | t | t | f | -1 | ******** | | f | | 16417
...

postgres=# SELECT * FROM pg_user;
usename | usesysid | usecreatedb | usesuper | userepl | usebypassrls | passwd | valuntil | useconfig
----------------------------+----------+-------------+----------+---------+--------------+----------+----------+-----------
...
relation-14 | 16403 | f | t | f | f | ******** | |
pgbouncer_auth_relation_14 | 16410 | f | t | f | f | ******** | |
relation_id_13 | 16417 | t | f | f | f | ******** | |
```

In this case, there are several records created to:
* `relation_id_13` - for relation between Application and PgBouncer
* `relation-14` - for relation between PgBouncer and PostgreSQL
* `pgbouncer_auth_relation_14` - to authenticate end-users, which connects PgBouncer

## Escalation and switching identity

Regular relation users can temporarily escalate their privileges to other predefined roles using PostgreSQL's role-switching features. There are two approaches:

- SET ROLE / RESET ROLE (standard, built-in)
- The `set_user` / `reset_user`

Both approaches are enabled by default in the charm.

Below they are explained in more details, including some examples.

### 1) Using SET ROLE and RESET ROLE

This is the standard PostgreSQL mechanism. A session can switch its current role to any role of which the current role is a member. Use the `SET ROLE` command to switch to a predefined role. Use RESET ROLE to return to the original role.

Example: escalate to `charmed_dml`:

```sql
-- In the application/session for the relation user, escalate to the predefined role.
SET ROLE charmed_dml;

-- Perform privileged operations that charmed_dml allows.

-- Then switch back to the original role.
RESET ROLE;
```

Notes:
- `SET ROLE` only works if the current role is a member of the target role (i.e. the target role was requested through the `extra-user-roles` relation field).

### 2) Using the set_user and reset_user to switch identity to another user

In some deployments you may want a member of `charmed_dba` to be able to become a different PostgreSQL user (either a non-superuser or the cluster superuser) for the duration of a session. The `set_user` extension provides functions that allow a caller to change the session's effective user identity.

Example: switch identity to a non-superuser role:

```sql
-- Called in a session where the relation user is a member of charmed_dba.
SELECT set_user('another_user'::TEXT);

-- Perform actions as another_user.

-- Then switch back to the previous identity.
SELECT reset_user();
```

Example: switch identity to the (cluster) superuser `operator`:

```sql
-- Called in a session where the relation user is a member of charmed_dba.
SELECT set_user_u('operator'::TEXT);

-- Perform superuser operations.

-- Then switch back to the previous identity.
SELECT reset_user();
```

Important security considerations:
- Prefer using `SET ROLE` when possible; use the `set_user` identity switching approach only when you need to assume an identity that cannot be achieved via role membership.

### Charmed PostgreSQL LDAP roles

To map LDAP users to PostgreSQL users, the dedicated LDAP groups have to be created before hand using [Data Integrator](https://charmhub.io/data-integrator) charm.
The result of such mapping will be a new PostgreSQL Roles:

```text
postgres=# SELECT * FROM pg_roles;
rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolbypassrls | rolconfig | oid
----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+-------------+---------------+--------------+-----------+-------
...
myrole | t | t | f | f | t | f | -1 | ******** | | f | | 16422
```
2 changes: 1 addition & 1 deletion docs/explanation/security/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Charmed PostgreSQL K8s can be deployed on top of several Kubernetes distribution

### Juju

Juju is the component responsible for orchestrating the entire lifecycle, from deployment to Day 2 operations. For more information on Juju security hardening, see the [Juju security page](https://canonical-juju.readthedocs-hosted.com/en/latest/user/explanation/juju-security/) and the [How to harden your deployment](https://documentation.ubuntu.com/juju/3.6/howto/manage-your-deployment/#harden-your-deployment) guide.
Juju is the component responsible for orchestrating the entire lifecycle, from deployment to Day 2 operations. For more information on Juju security hardening, see the [Juju security page](https://canonical-juju.readthedocs-hosted.com/en/latest/user/explanation/juju-security/) and the [How to harden your deployment](https://documentation.ubuntu.com/juju/3.6/howto/manage-your-juju-deployment/harden-your-juju-deployment/#harden-your-deployment) guide.

#### Cloud credentials

Expand Down
8 changes: 1 addition & 7 deletions docs/explanation/users.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,7 @@ juju relate postgresql-k8s myclientapp

### Extra user roles

When an application charm requests a new user through the relation/integration it can specify that the user should have the `admin` role in the `extra-user-roles` field. The `admin` role enables the new user to read and write to all databases (for the `postgres` system database it can only read data) and also to create and delete non-system databases.

```{note}
`extra-user-roles` is only supported by the modern interface `postgresql_client`. It is not supported for the legacy `pgsql` interface. R

Read more about the supported charm interfaces in [](/explanation/interfaces-and-endpoints).
```
When an application charm requests a new user through the relation/integration, it can specify that the user should be part of a predefined role to give them additional permissions. Please check [](/explanation/roles) for the list of available roles.

## Identity users

Expand Down