Els rols permeten controlar l'accés a les diferents bases de dades.
Introducció
Cada rol té assignats uns privilegis co ara login que permet al rol iniciar sessió, createdb que permet al rol crear una nova base de dades o superuser que permet al rol tenir tots els privilegis.
A més un rol pot ser membre d’altres rols.
Entorn de treball
Entra dins una màquina Windows Subsystem for Linux (WSL).
Crea un contenidor postgres:
docker run -d --name role -e POSTGRES_PASSWORD=password postgres:18Obre un terminal interactiu:
docker exec -it role psql -U postgresCrear un rol
Per crear un nou rol en un servidor PostgreSQL, utilitza la instrucció create role:
Per exemple, la següent instrucció utilitza la instrucció create role per crear un nou rol anomenat tortuga:
create role tortuga;Quan crees un rol, aquest és vàlid en totes les bases de dades dins del servidor de bases de dades (o clúster).
Pots consultar tots els rols de la base de dades en el catàleg del sistema pg_roles:
select rolname from pg_roles; rolname----------------------------- pg_database_owner ... pg_signal_autovacuum_worker postgres tortuga(18 rows)Observa que:
- Els rols els noms dels quals comencen amb
pg_són rols del sistema. postgresés un rol de superusuari creat per defecte.
També utilitzar l’ordre \du per mostrar tots els rols que has creat (també inclou el rol postgres):
\du List of roles Role name | Attributes-----------+------------------------------------------------------------ postgres | Superuser, Create role, Create DB, Replication, Bypass RLS tortuga | Cannot loginLa sortida indica que el rol tortuga no pot iniciar sessió.
Per permetre que tortuga iniciï sessió al servidor has d’afegir-li l’atribut login.
Atributs de rol
Els atributs d’un rol defineixen els privilegis per a aquest rol, incloent l’inici de sessió, l’estat de superusuari, la creació de bases de dades, la creació de rols, la gestió de contrasenyes, etc.
Aquesta és la sintaxi per crear un nou rol amb atributs:
create role name with option;En aquesta sintaxi, la paraula clau with és opcional.
L’opció pot ser un o més atributs com superuser, createdb, createrole, etc.
Crear rols d’inici de sessió
Per exemple, la següent instrucció crea un rol anomenat nobita que té el privilegi d’inici de sessió i una contrasenya inicial:
create role nobita login password '1234';Observa que col·loques la contrasenya entre cometes simples (').
Aquí tens la nova llista de rols:
\du List of roles Role name | Attributes-----------+------------------------------------------------------------ nobita | postgres | Superuser, Create role, Create DB, Replication, Bypass RLS tortuga | Cannot loginSurt de la base de dades:
\qAra pots utilitzar el rol nobita per iniciar sessió al servidor de bases de dades PostgreSQL utilitzant l’eina client psql:
docker exec -it role psql -U nobita -d postgresEt demanarà una contrasenya … 😐 (en aquest context no).
Has d’introduir la contrasenya que vas introduir a la instrucció create role per iniciar sessió al servidor.
Una connexió “psql” sempre es fa a una base de dades i, per defecte, es fa a la base de dades que coincideix amb el nom del rol que utilitzes per connectar-te.
Com que no existeix cap base de dades nobita has de conectar-te de manera explícita a la base de dades postgres.
Si no ho fas, passa això:
docker exec -it rol psql -U nobitapsql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: database "nobita" does not existPots verificar que és el rol nobita qui està connectat:
select current_user; current_user-------------- nobita(1 row)Crear rols de superusuari
La següent instrucció crea un rol anomenat doraemon que té l’atribut de superuser:
create role doraemon superuser login password '1234';Però com que ara ets l’usuari nobita, no pots crear altres usuaris.
Només un rol de superusuari pot crear un altre rol de superusuari:
ERROR: permission denied to create roleDETAIL: Only roles with the CREATEROLE attribute may create roles.Canvia al rol postgres:
set role postgres;Tampoc 😺 … És una base de dades segura!
ERROR: permission denied to set role "postgres"Tanca la sessió i torna a entrar amb el rol postgres:
docker exec -it rol psql -U postgresCrea el superusuari doraemon:
create role doraemon superuser login password '1234';Canvia a l’usuari doraemon:
set role doraemon;El rol de superusuari té tots els permisos dins del servidor.
Per tant, només has de crear el rol de superusuari quan sigui necessari.
Crear rols amb permís de creació de bases de dades
Si vols crear rols que tinguin el privilegi de creació de bases de dades, pots utilitzar l’atribut createdb:
create role shizuka createdb login password '1234';Canvia al rol shizuka i crea la base de dades planet:
set role shizuka;create database universe;Crear rols amb un període de validesa
Per establir una data i hora després de la qual la contrasenya del rol ja no sigui vàlida, utilitza l’atribut valid until:
valid until 'timestamp'Un segon després del marcat per timestamp la contrasenya ja no serà válida.
Per exemple, la següent instrucció crea un rol dev_api amb contrasenya vàlida fins a …:
create role takeshi with login password '1234' valid until '2025-11-20';ERROR: permission denied to create roleDETAIL: Only roles with the CREATEROLE attribute may create roles.El rol shizuka només té permís per crear bases de dades, no rols.
Torna al rol de postgres i crea el rol shizuka.
set role postgres;create role shizuka with login password '1234' valid until '2025-11-20';Crear rols amb límit de connexió
Per especificar el nombre de connexions simultànies que pot fer un rol, utilitza l’atribut connection limit.
La següent instrucció crea un nou rol anomenat api que pot fer 1000 connexions simultànies:
create role api login password '1234' connection limit 1000;Conclusió
Ara tens diversos rols en la teva base de dades amb permisos diferents:
\du List of roles Role name | Attributes-----------+------------------------------------------------------------ api | 1000 connections doraemon | Superuser nobita | postgres | Superuser, Create role, Create DB, Replication, Bypass RLS shizuka | Create DB takeshi | Password valid until 2025-11-20 00:00:00+00 tortuga | Cannot logingrant
After creating a role with the LOGIN attribute, the role can log in to the PostgreSQL database server.
However, it cannot do anything to the database objects like tables, views, functions, etc. For example, the role cannot select data from a table or execute a specific function.
To allow a role to interact with database objects, you need to grant privileges on the database objects to the role using the grant statement.
The following shows the simple form of the GRANT statement that grants one or more privileges on a table to a role:
GRANT privilege_list | ALLON table_nameTO role_name;In this syntax:
- First, specify the privilege_list that can be SELECT, INSERT,UPDATE, DELETE,TRUNCATE, etc. Use the ALL option to grant all privileges on a table to the role.
- Second, provide the name of the table after the ON keyword.
- Third, indicate the name of the role to which you want to grant privileges.
Examples
Create a new user role called joe that can log in to the PostgreSQL server:
create role joe login password 'password';Create a new database, for example acme, and connect to it:
create database acme;Create a new table called candidates:
create table candidates ( candidate_id int generated always as identity, first_name varchar(100) not null, last_name varchar(100) not null, email varchar(255) not null unique, phone varchar(25) not null, primary key(candidate_id));Use the role joe to log in to the PostgreSQL server in a separate session.
Attempt to select data from the candidates table from the joe’s session:
SELECT * FROM candidates;PostgreSQL issued an error:
ERROR: permission denied for table candidatesTo grant the SELECT privilege on the candidates table to the role joe, you execute the following GRANT statement in the postgres’ session:
GRANT SELECTON candidatesTO joe;Now, you can select data from the candidates table using the joe role:
SELECT * FROM candidates;PostgreSQL returns an empty result set instead of an error.
Execute the following INSERT statement:
INSERT INTO candidates(first_name, last_name, email, phone)VALUES('Joe','Com','joe.com@example.com','408-111-2222');PostgreSQL issued the following error because joe does not have the INSERT privilege on the candidates table:
ERROR: permission denied for table candidatesGrant INSERT, UPDATE, and DELETE privileges on the candidates table to the role joe:
GRANT INSERT, UPDATE, DELETEON candidatesTO joe;Execute the INSERT statement again from the joe’s session:
INSERT INTO candidates(first_name, last_name, email, phone)VALUES('Joe','Com','joe.com@example.com','408-111-2222');Now, joe can insert data into the candidates table. Additionally, it can update or delete data from the table.
More examples
Grant all privileges on a table to a role
The following statement grants all privileges on the candidates table to the role joe:
GRANT ALLON candidatesTO joe;Grant all privileges on all tables in a schema to a role
The following statement grants all privileges on all tables in the public schema of the database to the role joe:
GRANT ALLON ALL TABLESIN SCHEMA "public"TO joe;revoke
he REVOKE statement revokes previously granted privileges on database objects from a role.
The following shows the syntax of the REVOKE statement that revokes privileges on one or more tables from a role:
REVOKE privilege | ALLON TABLE table_name | ALL TABLES IN SCHEMA schema_nameFROM role_name;In this syntax:
- First, specify one or more privileges that you want to revoke or use the ALL option to revoke all privileges.
- Second, provide the name of the table after the ON keyword or use the ALL TABLES to revoke specified privileges from all tables in a schema.
- Third, specify the name of the role from which you want to revoke privileges.
Examples
Create a new role called jim:
CREATE ROLE jim;grant all privileges to the role jim on the candidates table:
GRANT ALL ON candidates TO jim;To revoke all privileges on the candidates table from the role jim, you use REVOKE statement with the ALL option like this:
REVOKE ALL ON candidates FROM jim;Role Membership
In PostgreSQL, a group role is a role that serves as a container for other individual roles.
Unlike individual roles, which typically represent users, a group role is used to manage collections of roles.
Typically, you create a role to represent a group and then grant a membership in the group role to individual roles.
Group roles allow you to simplify permission management. Instead of granting privileges to individual roles, you can group these roles into a group, grant privileges to a group role, and all the members of that group role will inherit those privileges.
Group roles can have individual roles or other group roles as their members. This allows you to create hierarchical structures where you can manage privileges at different levels.
Individual roles can be members of multiple group roles. This allows for flexible assignment of permissions and roles within the database.
Creating a group role
Creating a group role is like creating a role by using the CREATE ROLE statement:
CREATE ROLE group_role;In this syntax, you specify the name of the group role after the CREATE ROLE keyword.
By convention, a group role does not have the LOGIN privilege, meaning that you will not use the group role to log in to PostgreSQL even though you can.
For example, the following statement creates a group role called sales:
create role sales;When you use the \du command in the psql tool, you will see that the group roles are listed together with individual roles:
List of roles Role name | Attributes-----------+------------------------------------------------------------ postgres | Superuser, Create role, Create DB, Replication, Bypass RLS sales | Cannot loginTo add a role to a group, you use the following form of the GRANT statement:
GRANT group_role TO role;In this syntax:
- First, specify the name of the group role after the GRANT keyword.
- Second, specify the name of the role after the TO keyword.
For example, the following statement creates a new role alice:
create role alice with login password 'password';This CREATE ROLE implicitly uses the INHERIT attribute to ensure that the role alice automatically inherits privileges from the group roles to which it belongs.
Add alice to the group role sales:
grant sales to alice;After you execute this statement, the alice role will automatically inherit all privileges of the sales group role if the alice role has INHERIT attribute.
If you don’t want the role alice to inherit the privileges of its group roles, you can use the NOINHERIT attribute:
create role alice with login noinherit password 'password';The following grants the SELECT privilege on the candidates table to the sales group role:
GRANT SELECT ON candidates TO sales;The role alice will automatically inherit the SELECT privilege on the rental table from the sales group role.
Let’s test it out.
grant select on candidates to sales;set role alice;select * from candidates;The output indicates that the role alice has the SELECT privilege on the candidates table even though we did not explicitly assign it.
Removing a role to a group role
To remove a role from a group role, you use the REVOKE statement:
REVOKE group_role FROM role;In this syntax:
- First, specify the name of the group role after the REVOKE keyword.
- Second, specify the name of the role after the FROM keyword.
A useful tip to remember when using GRANT and REVOKE statements with the group role is that the group role should come first, followed by the individual role.
For example, the following statement uses the REVOKE statement to remove the role alice from the group role sales:
REVOKE sales FROM alice;Notice that PostgreSQL does not permit circular membership loops, where a role is the member of another role and vice versa.
current_user
The PostgreSQL CURRENT_USER is a function that returns the name of the currently logged-in database user.
Here’s the syntax of the CURRENT_USER function:
current_user;The function returns the name of the current effective user within the session.
In other words, if you use the SET ROLE statement to change the role of the current user to the new one, the CURRENT_USER will reflect the new role.
In PostgreSQL, a role with the LOGIN attribute represents a user. Therefore, we use the terms role and user interchangeably.
To get the original user who connected to the session, you use the SESSION_USER function.
set role alice;select current_user; current_user-------------- alice(1 row)Use the SESSION_USER function to retrieve the original user who connected to the session:
select session_user; session_user-------------- postgres(1 row)The SESSION_USER function returns postgres, not alice.
Tasks
- Create DB med and connect to it:
- create database med;
- \c med
- Create table patients: create table patients …;
- Verify:
- \d patients
- Goal: Create three roles: doctor, nurse, receptionist. Only doctor and nurse can log in.
- Steps:
- create role doctor login password ‘docpass’;
- create role nurse login password ‘nursepass’;
- create role receptionist nologin; — group role
- \du to verify attributes.
- Goal: Show default denial and then grant read.
- Steps:
- As postgres, insert sample data:
- insert into patients(first_name,last_name,birth_date,diagnosis,phone) values (‘Ana’,‘Lopez’,‘1982-04-01’,‘Hypertension’,‘555-0001’);
- In another session, connect as doctor to med.
- Try: select * from patients; → Expect: ERROR: permission denied for table patients
- Back as postgres, grant read:
- grant select on patients to doctor;
- As doctor, run select again → Should work, return rows.
- As postgres, insert sample data:
- Goal: Write, but not delete.
- Steps:
- As nurse, test insert (should fail initially):
- insert into patients(first_name,last_name,birth_date,diagnosis,phone) values(‘Bob’,‘Cruz’,‘1990-05-10’,‘Flu’,‘555-0002’); → Expect: permission denied
- As postgres, grant insert, update on patients to nurse:
- grant insert, update on patients to nurse;
- As nurse, retry insert → Should succeed.
- As nurse, attempt delete:
- delete from patients where phone=‘555-0001’; → Expect: permission denied
- As nurse, test insert (should fail initially):
- Goal: Hide phone from nurse via a view; give doctor full access.
- Steps:
- As postgres, create a view without phone:
- create view patients_public as select patient_id, first_name, last_name, birth_date, diagnosis from patients;
- Revoke nurse direct select on table (keep insert/update from previous task):
- revoke select on patients from nurse;
- Grant nurse select on the view:
- grant select on patients_public to nurse;
- As nurse:
- select * from patients_public; → Works, no phone column.
- select phone from patients; → Expect: permission denied
- Ensure doctor keeps table-level select:
- as doctor: select phone from patients; → Works.
- As postgres, create a view without phone:
- Goal: Use group role to manage front-desk visibility (read-only limited columns).
- Steps: Ensure receptionist role exists and cannot login.
- Create a limited view:
- create view patients_frontdesk as select patient_id, first_name, last_name, phone from patients;
- Grant:
- grant select on patients_frontdesk to receptionist;
- Create a user account and add to group:
- create role alice_recep login password ‘pass’;
- grant receptionist to alice_recep;
- As alice_recep:
- select * from patients_frontdesk; → Works
- select * from patients; → Expect: permission denied
- Verify inheritance behavior:
- select current_user, session_user; — See effective and original user
- Goal: Remove receptionist access cleanly.
- Steps:
- As postgres:
- revoke select on patients_frontdesk from receptionist;
- As alice_recep:
- select * from patients_frontdesk; → Expect: permission denied
- Remove membership:
- revoke receptionist from alice_recep;
- Verify \du shows membership removed.
- As postgres: