diff --git a/knowledge base/postgresql.md b/knowledge base/postgresql.md
index ea2b8bf..5f18a18 100644
--- a/knowledge base/postgresql.md
+++ b/knowledge base/postgresql.md
@@ -1,6 +1,9 @@
# PostgreSQL
1. [TL;DR](#tldr)
+1. [Extensions of interest](#extensions-of-interest)
+ 1. [PostGIS](#postgis)
+ 1. [`postgresql_anonymizer`](#postgresql_anonymizer)
1. [Further readings](#further-readings)
1. [Sources](#sources)
@@ -23,9 +26,12 @@ DB-specific roles).
Extensions in PostgreSQL are managed per database.
+
+ Setup
+
```sh
# Installation.
-brew install 'postgresql@14'
+brew install 'postgresql@16'
sudo dnf install 'postgresql' 'postgresql-server'
sudo zypper install 'postgresql15' 'postgresql15-server'
@@ -48,6 +54,11 @@ user = master
EOF
```
+
+
+
+ Usage
+
```sh
# Connect to servers via CLI client.
# If not given:
@@ -99,12 +110,73 @@ createuser 'dummyuser' -e --pwprompt && dropuser 'dummyuser'
scram-sha-256 'mySecretPassword'
```
+```sql
+-- Load extensions from the underlying operating system
+-- They must be already installed on the instance
+ALTER SYSTEM SET shared_preload_libraries = 'anon';
+ALTER DATABASE postgres SET session_preload_libraries = 'anon';
+```
+
+
+
+## Extensions of interest
+
+### PostGIS
+
+TODO
+
+### `postgresql_anonymizer`
+
+Extension to mask or replace personally identifiable information or other sensitive data in a DB.
+
+Refer [`postgresql_anonymizer`][postgresql_anonymizer] and [An In-Depth Guide to Postgres Data Masking with Anonymizer].
+
+Admins declare masking rules using the PostgreSQL Data Definition Language (DDL) and specify the anonymization strategy
+inside each tables' definition.
+
+
+ Example
+
+```sh
+docker run --rm -d -e 'POSTGRES_PASSWORD=postgres' -p '6543:5432' 'registry.gitlab.com/dalibo/postgresql_anonymizer'
+psql -h 'localhost' -p '6543' -U 'postgres' -d 'postgres' -W
+```
+
+```sql
+=# SELECT * FROM people LIMIT 1;
+ id | firstname | lastname | phone
+----+-----------+----------+------------
+ T1 | Sarah | Conor | 0609110911
+
+-- 1. Activate the dynamic masking engine
+=# CREATE EXTENSION IF NOT EXISTS anon CASCADE;
+=# SELECT anon.start_dynamic_masking();
+
+-- 2. Declare a masked user
+=# CREATE ROLE skynet LOGIN PASSWORD 'skynet';
+=# SECURITY LABEL FOR anon ON ROLE skynet IS 'MASKED';
+
+-- 3. Declare masking rules
+=# SECURITY LABEL FOR anon ON COLUMN people.lastname IS 'MASKED WITH FUNCTION anon.fake_last_name()';
+=# SECURITY LABEL FOR anon ON COLUMN people.phone IS 'MASKED WITH FUNCTION anon.partial(phone,2,$$******$$,2)';
+
+-- 4. Connect with the masked user and test masking
+=# \connect - skynet
+=# SELECT * FROM people LIMIT 1;
+ id | firstname | lastname | phone
+----+-----------+----------+------------
+ T1 | Sarah | Morris | 06******11
+```
+
+
+
## Further readings
- [Docker image]
- [Bidirectional replication in PostgreSQL using pglogical]
- [What is the pg_dump command for backing up a PostgreSQL database?]
- [How to SCRAM in Postgres with pgBouncer]
+- [`postgresql_anonymizer`][postgresql_anonymizer]
### Sources
@@ -114,6 +186,7 @@ scram-sha-256 'mySecretPassword'
- [The password file]
- [How to Generate SCRAM-SHA-256 to Create Postgres 13 User]
- [PostgreSQL: Get member roles and permissions]
+- [An In-Depth Guide to Postgres Data Masking with Anonymizer]
+[an in-depth guide to postgres data masking with anonymizer]: https://thelinuxcode.com/postgresql-anonymizer-data-masking/
[bidirectional replication in postgresql using pglogical]: https://www.jamesarmes.com/2023/03/bidirectional-replication-postgresql-pglogical.html
[connect to a postgresql database]: https://www.postgresqltutorial.com/connect-to-postgresql-database/
[how to generate scram-sha-256 to create postgres 13 user]: https://stackoverflow.com/questions/68400120/how-to-generate-scram-sha-256-to-create-postgres-13-user
[how to scram in postgres with pgbouncer]: https://www.crunchydata.com/blog/pgbouncer-scram-authentication-postgresql
+[postgresql_anonymizer]: https://postgresql-anonymizer.readthedocs.io/en/stable/
[postgresql: get member roles and permissions]: https://www.cybertec-postgresql.com/en/postgresql-get-member-roles-and-permissions/
[what is the pg_dump command for backing up a postgresql database?]: https://www.linkedin.com/advice/3/what-pgdump-command-backing-up-postgresql-ke2ef
diff --git a/snippets/postgresql.sql b/snippets/postgresql.sql
index 637424e..b3eeba4 100644
--- a/snippets/postgresql.sql
+++ b/snippets/postgresql.sql
@@ -18,6 +18,12 @@ SELECT version();
\conninfo
+-- Load extensions globally in the instance
+-- If supported (no RDS)
+ALTER SYSTEM SET shared_preload_libraries = 'anon';
+ALTER DATABASE postgres SET session_preload_libraries = 'anon';
+
+
-- List databases
\l
\list+
@@ -62,8 +68,25 @@ DROP SCHEMA IF EXISTS mundane CASCADE;
-- List tables
\d
+\dt
\dt+
+-- Create tables
+CREATE TABLE people (
+ id char(2) PRIMARY KEY,
+ firstname varchar(40) NOT NULL,
+ lastname varchar(40) NOT NULL,
+ phone varchar(20) NOT NULL
+);
+
+-- Show table structure
+\d sales
+\d+ clients
+
+
+-- Insert data
+INSERT INTO people(id,firstname,lastname,phone) VALUES ('T1','Sarah','Conor','0609110911');
+
-- Revoke *default* privileges
ALTER DEFAULT PRIVILEGES IN SCHEMA cache REVOKE select ON TABLES FROM sales;
@@ -75,6 +98,8 @@ ALTER DEFAULT PRIVILEGES FOR ROLE juan IN SCHEMA cache REVOKE all ON TABLES FROM
\du+
-- List users only
SELECT usename FROM pg_catalog.pg_user;
+-- List roles only
+SELECT rolname FROM pg_catalog.pg_roles;
-- Check the current user has SuperUser privileges
SHOW is_superuser;
@@ -85,7 +110,7 @@ SHOW is_superuser;
-- Does *not* support IF NOT EXISTS
CREATE ROLE miriam;
CREATE ROLE miriam WITH LOGIN PASSWORD 'jw8s0F4' VALID UNTIL '2005-01-01';
-CREATE USER mike;
+CREATE USER mike IN ROLE engineers;
-- Grant roles SuperUser privileges
-- The role granting privileges must be already SuperUser
@@ -99,18 +124,22 @@ ALTER USER mark CREATEDB REPLICATION;
ALTER ROLE miriam CREATEROLE CREATEDB;
-- Change passwords
+ALTER USER mike WITH PASSWORD NULL;
ALTER USER jonathan WITH PASSWORD 'seagull5-pantomime-Resting';
ALTER ROLE samantha WITH PASSWORD 'Wing5+Trunks3+Relic2' VALID UNTIL 'August 4 12:00:00 2024 +1';
-- Change password's validity
ALTER ROLE fred VALID UNTIL 'infinity';
--- Rename
+-- Rename roles
ALTER ROLE manager RENAME TO boss;
-- Assign roles to users
GRANT rds_superuser TO mike;
+-- Remove role memberships from users
+REVOKE engineers FROM mike;
+
-- Close the connection to the current DB
\q
@@ -121,10 +150,13 @@ GRANT rds_superuser TO mike;
SELECT rolpassword from pg_authid where rolname = 'admin';
--- Show extensions
+-- Show available extensions
+SELECT name FROM pg_available_extensions ORDER BY name;
+
+-- Show installed extensions
\dx
SELECT * FROM pg_extension;
-SELECT extname FROM pg_extension;
+SELECT extname FROM pg_extension ORDER BY extname;
-- Show extensions versions
SELECT postgis_version(), postgis_full_version(), postgis_lib_version();