PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 12.22 » Annexes » Modules supplémentaires fournis » sepgsql

F.35. sepgsql

sepgsql est un module chargeable ajoutant le support des contrôles d'accès par label basé sur la politique de sécurité de SELinux.

Avertissement

L'implémentation actuelle a des limitations importantes et ne force pas le contrôle d'accès pour toutes les actions. Voir Section F.35.7.

F.35.1. Aperçu

Ce module s'intègre avec SELinux pour fournir une couche de vérification de sécurité supplémentaire qui va au-delà de ce qui est déjà fournit par PostgreSQL. De la perspective de SELinux, ce module permet à PostgreSQL de fonctionner comme un gestionnaire d'objet en espace utilisateur. Chaque accès à une table ou à une fonction initié par une requête DML sera vérifié par rapport à la politique de sécurité du système. Cette vérification est en plus des vérifications de droits SQL habituels effectuées par PostgreSQL.

Les décisions de contrôle d'accès de SELinux sont faites en utilisant les labels de sécurité qui sont représentés par des chaînes comme system_u:object_r:sepgsql_table_t:s0. Chaque décision de contrôle d'accès implique deux labels : celui de l'utilisateur tentant de réaliser l'action et celui de l'objet sur lequel l'action est réalisée. Comme ces labels peuvent être appliqués sur tout type d'objet, les décisions de contrôle d'accès pour les objets stockés dans la base peuvent être (et avec ce module, sont) sujets au même critère général utilisé pour les objets de tout type (par exemple les fichiers). Ce concept a pour but de permettre la mise en place d'une politique centralisée pour protéger l'information quelque soit la façon dont l'information est stockée.

L'instruction SECURITY LABEL permet d'affecter un label de sécurité à un objet de la base de données.

F.35.2. Installation

sepgsql peut seulement être utilisé sur Linux 2.6.28 ou ultérieur, avec SELinux activé. Il n'est pas disponible sur les autres plateformes. Vous aurez aussi besoin de libselinux ou ultérieur et de selinux-policy 2.1.10 ou ultérieur (même si certaines distributions peuvent proposer les règles nécessaires dans des versions antérieures de politique).

La commande sestatus vous permet de vérifier le statut de SELinux. Voici un affichage standard :

$ sestatus
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 24
Policy from config file:        targeted
   

Si SELinux est désactivé ou non installé, vous devez tout d'abord configurer ce produit avant d'utiliser ce module.

Pour construire ce module, ajoutez l'option --with-selinux dans votre commande configure lors de la compilation de PostgreSQL. Assurez-vous que le RPM libselinux-devel est installé au moment de la construction.

Pour utiliser ce module, vous devez ajouter sepgsql dans le paramètre shared_preload_libraries du fichier postgresql.conf. Le module ne fonctionnera pas correctement s'il est chargé d'une autre façon. Une fois que le module est chargé, vous devez exécuter sepgsql.sql dans chaque base de données. Cela installera les fonctions nécessaires à la gestion des labels de sécurité et affectera des labels initiaux de sécurité.

Voici un exemple montrant comment initialiser un répertoire de données avec les fonctions sepgsql et les labels de sécurité installés. Ajustez les chemins de façon approprié pour que cela corresponde à votre installation :

$ export PGDATA=/path/to/data/directory
 $ initdb
 $ vi $PGDATA/postgresql.conf
  modifiez
    #shared_preload_libraries = ''                # (change requires restart)
  en
    shared_preload_libraries = 'sepgsql'          # (change requires restart)
 $ for DBNAME in template0 template1 postgres; do
    postgres --single -F -c exit_on_error=true $DBNAME \
      </usr/local/pgsql/share/contrib/sepgsql.sql >/dev/null
   done
  

Notez que vous pourriez voir les notifications suivantes, suivant la combinaison de versions particulières de libselinux et de selinux-policy.

/etc/selinux/targeted/contexts/sepgsql_contexts:  line 33 has invalid object type db_blobs
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 36 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 37 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 38 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 39 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 40 has invalid object type db_language
   

Ces messages ne sont graves et peuvent être ignorés sans conséquence.

Si le processus d'installation se termine sans erreur, vous pouvez commencer à lancer le serveur normalement.

F.35.3. Tests de régression

Dû à la nature de SELinux, exécuter les tests de régression pour sepgsql nécessite quelques étapes de configuration supplémentaires, certaines se faisant en tant qu'utilisateur root. Les tests de régression ne seront pas exécutés par une commande make check ou make installcheck ordinaire ; vous devez faire la configuration puis appeler le script de test manuellement. Les tests s'exécuteront dans le répertoire contrib/sepgsql du répertoire des sources de PostgreSQL, préalablement configuré. Bien que cela nécessite un arbre de construction, les tests sont conçus pour être exécutés par un serveur déjà installé, donc comparable à make installcheck, et non pas make check.

Tout d'abord, configurez sepgsql dans une base de données fonctionnelle d'après les instructions comprises dans Section F.35.2. Notez que l'utilisateur du système d'exploitation doit être capable de se connecter à la base de données en tant que superutilisateur sans authentification par mot de passe.

Ensuite, construisez et installez le paquet de politique pour les tests de régression. Le fichier sepgsql-regtest est un paquet de politique à but spécial. Il fournit un ensemble de règles à autoriser pendant les tests de régression. Il doit être construit à partir du fichier source de politique sepgsql-regtest.te, ce qui se fait en utilisant make avec un fichier Makefile fourni par SELinux. Vous aurez besoin de localiser le Makefile approprié sur votre système ; le chemin affiché ci-dessous est seulement un exemple. Une fois construit, installez ce paquet de politique en utilisant la commande semodule, qui charge les paquets de politique fournis dans le noyau. Si ce paquet est correctement installé, semodule -l doit lister sepgsql-regtest comme un paquet de politique disponible :

$ cd .../contrib/sepgsql
$ make -f /usr/share/selinux/devel/Makefile
$ sudo semodule -u sepgsql-regtest.pp
$ sudo semodule -l | grep sepgsql
sepgsql-regtest 1.07
  

Pour des raisons de sécurité, les règles de sepgsql-regtest ne sont pas activés par défaut. Le paramètre sepgsql_regression_test_mode active les règles pour le lancement des tests de régression. Il peut être activé en utilisant la commande setsebool :

$ sudo setsebool sepgsql_regression_test_mode on
$ getsebool sepgsql_regression_test_mode
  

Ensuite, vérifiez que votre shell est exécuté dans le domaine unconfined_t :

$ ./test_sepgsql
  

Ce script tentera de vérifier que vous avez fait correctement toutes les étapes de configuration, puis il lancera les tests de régression du module sepgsql.

Une fois les tests terminés, il est recommandé de désactiver le paramètre sepgsql_regression_test_mode :

$ sudo setsebool sepgsql_regression_test_mode off
  

Vous pouvez préférer supprimer complètement la politique sepgsql-regtest :

$ sudo semodule -r sepgsql-regtest
  

F.35.4. Paramètres GUC

sepgsql.permissive (boolean)

Ce paramètre active sepgsql pour qu'il fonctionne en mode permissif, quelque soit la configuration du système. La valeur par défaut est off. Ce paramètre es configurable dans le fichier postgresql.conf et sur la ligne de commande.

Quand ce paramètre est activé, sepgsql fonctionne en mode permissif, même si SELinux fonctionne en mode forcé. Ce paramètre est utile principalement pour des tests.

sepgsql.debug_audit (boolean)

Ce paramètre active l'affichage de messages d'audit quelque soit la configuration de la politique. La valeur par défaut est off, autrement dit les messages seront affichés suivant la configuration du système.

La politique de sécurité de SELinux a aussi des règles pour contrôler la trace des accès. Par défaut, les violations d'accès sont tracées, contrairement aux accès autorisés.

Ce paramètre force l'activation de toutes les traces, quelque soit la politique du système.

F.35.5. Fonctionnalités

F.35.5.1. Classes d'objet contrôlé

Le modèle de sécurité SELinux décrit toutes les règles de contrôle d'accès comme des relations entre une entité sujet (habituellement le client d'une base) et une entité objet (tel que l'objet base de données). Les deux sont identifiés par un label de sécurité. Si un accès à un objet sans label est tenté, l'objet est traité comme si le label unlabeled_t lui est affecté.

Actuellement, sepgsql autorise l'affectation de label de sécurité aux schémas, tables, colonnes, séquences, vues et fonctions. Quand sepgsql est en cours d'utilisation, des labels de sécurité sont automatiquement affectés aux objets de la base au moment de leur création. Ce label est appelé un label de sécurité par défaut et est configuré par la politique de sécurité du système, qui prend en entrée le label du créateur, le label affecté à l'objet parent du nouvel objet et en option le nom de l'objet construit.

Un nouvel objet base de données hérite en gros du label de sécurité de l'objet parent, sauf quand la politique de sécurité a des règles spéciales, connues sous le nom de règles de transition, auquel cas un label différent est affecté. Pour les schémas, l'objet parent est la base de données ; pour les tables, séquences, vues et fonctions, il s'agit du schéma ; pour les colonnes, il s'agit de la table.

F.35.5.2. Droits DML

Pour les tables, db_table:select, db_table:insert, db_table:update ou db_table:delete sont vérifiés pour toutes les tables cibles référencées, suivant l'ordre de l'instruction. De plus, db_table:select est aussi vérifié pour toutes les tables qui contiennent des colonnes référencées dans la clause WHERE ou RETURNING, comme source de données d'un UPDATE, et ainsi de suite.

Les droits au niveau colonne seront aussi vérifiés pour chaque colonne référencée. column_db:select est vérifié sur les colonnes lues en utilisant SELECT, mais aussi celles référencées dans d'autres instructions DML ; column_db:update ou column_db:insert sear aussi vérifié pour les colonnes modifiées par UPDATE ou INSERT.

Bien sûr, il vérifie aussi db_column:update ou db_column:insert sur la colonne en cours de modification par UPDATE ou INSERT.

Par exemple :

UPDATE t1 SET x = 2, y = func1(y) WHERE z = 100;
    

Ici, column_db:update sera vérifié pour t1.x car elle est mise à jour, column_db:{select update} sera vérifié pour t1.y car elle est à la fois mise à jour et référencée, et column_db:select sera vérifié pour t1.z car elle est référencée. db_table:{select update} vérifiera aussi la table.

Pour les séquences, db_sequence:get_value est vérifié quand nous référençons un objet séquence en utilisant SELECT ; néanmoins, notez que nous ne vérifions pas les droits d'exécution sur les fonctions correspondantes, par exemple lastval().

Pour les vues, db_view:expand devrait être vérifié, et ensuite tous les autres droits des objets dus à l'aplatissement de la vue, individuellement.

Pour les fonctions, db_procedure:{execute} sera vérifié quand un utilisateur essaie d'exécuter une fonction dans une requête ou en utilisant l'appel « fast-path ». Si cette fonction est déclarée comme étant de confiance, il vérifie aussi le droit db_procedure:{entrypoint} pour s'assurer qu'il peut s'exécuter comme un point d'entrée d'une procédure de confiance.

Pour accéder à tout objet d'un schéma, le droit db_schema:search est requis sur le schéma contenant l'objet. Quand un objet est référencé sans le nom du schéma, les schémas qui n'ont pas ce droit ne seront pas recherchés (exactement le même comportement que l'absence du droit USAGE sur le schéma). Si une qualification explicite du schéma est présent, une erreur surviendra si l'utilisateur n'a pas le droit requis sur le schéma nommé.

Le client doit être autorisé à accéder à toutes les tables et colonnes référencées, même si elles proviennent de vues qui ont été aplaties, pour pouvoir appliquer des règles de contrôles d'accès cohérentes indépendamment de la manière dont le contenu des tables est référencé.

Le système des droits de la base, par défaut, autorise les superutilisateurs de la base à modifier les catalogues systèmes en utilisant des commandes DML, et de référencer ou modifier les tables TOAST. Ces opérations sont interdites quand sepgsql est activé.

F.35.5.3. Droits DDL

SELinux définit plusieurs droits pour contrôler les opérations standards pour chaque type d'objet : création, modification, suppression et changement du label de sécurité. De plus, certains types d'objet ont des droits spéciaux pour contrôler leur opérations caractéristiques : ajout ou suppression d'entrées dans un schéma particulier.

Créer un objet de bases de données nécessite le droit create. SELinux acceptera ou refusera ce droit en se basant sur le label de sécurité du client et sur le label de sécurité proposé pour le nouvel objet. Dans certains cas, des droits supplémentaires sont demandés :

  • CREATE DATABASE requiert en plus le droit getattr pour la base de données source ou modèle.

  • Créer un schéma requiert en plus le droit add_name sur le schéma parent.

  • Créer une table requiert en plus le droit de créer chaque colonne de la table, tout comme si chaque colonne de la table était un objet séparé de haut-niveau.

  • Créer une fonction marquée LEAKPROOF requiert en plus le droit install. (Ce droit est aussi vérifié quand LEAKPROOF est configuré pour une fonction existante.)

Quand la commande DROP est exécutée, drop sera vérifié sur l'objet qui doit être supprimé. Les droits seront aussi vérifiés pour les objets supprimés indirectement via CASCADE. La suppression des objets contenus dans un schéma particulier (tables, vues, séquences et fonctions) nécessite habituellement remove_name sur le schéma.

Quand la commande ALTER est exécutée, setattr sera vérifié sur l'objet en cours de modification pour chaque type d'objet, sauf pour les objets sous-jacents comme les index ou les triggers d'une table. Pour ces derniers, les droits sont vérifiés sur l'objet parent. Dans certains cas, des droits supplémentaires sont réclamés :

  • Déplacer un objet vers un nouveau schéma réclame en plus le droit remove_name sur l'ancien schéma et le droit add_name sur le nouveau schéma.

  • Configurer l'attribut LEAKPROOF sur une fonction requiert le droit install.

  • Utiliser SECURITY LABEL sur un objet requiert en plus le droit relabelfrom pour l'objet en conjonction avec son ancien label et le droit relabelto pour l'objet en conjonction avec son nouveau label. (Dans les cas où plusieurs fournisseurs de label sont installés et que l'utilisateur essaie de configurer un label de sécurité mais qui est géré par SELinux, seul setattr peut être vérifié ici. Cela ne peut pas se faire actuellement à cause des restrictions de l'implémentation.)

F.35.5.4. Procédures de confiance

Les procédures de confiance sont similaires aux fonctions dont la sécurité est définie à la création ou aux commandes set-uid. SELinux propose une fonctionnalité qui permet d'autoriser un code de confiance à s'exécuter en utilisant un label de sécurité différent de celui du client, généralement pour donner un accès hautement contrôlé à des données sensibles (par exemple, des lignes peuvent être omises ou la précision des valeurs stockées peut être réduite). Que la fonction agisse ou pas comme une procédure de confiance est contrôlé par son label de sécurité et la politique de sécurité du système d'exploitation. Par exemple :

postgres=# CREATE TABLE customer (
               cid     int primary key,
               cname   text,
               credit  text
           );
CREATE TABLE
postgres=# SECURITY LABEL ON COLUMN customer.credit
               IS 'system_u:object_r:sepgsql_secret_table_t:s0';
SECURITY LABEL
postgres=# CREATE FUNCTION show_credit(int) RETURNS text
             AS 'SELECT regexp_replace(credit, ''-[0-9]+$'', ''-xxxx'', ''g'')
                        FROM customer WHERE cid = $1'
           LANGUAGE sql;
CREATE FUNCTION
postgres=# SECURITY LABEL ON FUNCTION show_credit(int)
               IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
SECURITY LABEL
   

Les opérations ci-dessus doivent être réalisées par un utilisateur administrateur.

postgres=# SELECT * FROM customer;
ERROR:  SELinux: security policy violation
postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
 cid | cname  |     show_credit
-----+--------+---------------------
   1 | taro   | 1111-2222-3333-xxxx
   2 | hanako | 5555-6666-7777-xxxx
(2 rows)
   

Dans ce cas, un utilisateur standard ne peut pas faire référence à customer.credit directement mais une procédure de confiance comme show_credit lui permet d'afficher le numéro de carte de crédit des clients, avec quelques chiffres masqués.

F.35.5.5. Transitions de domaine dynamique

Il est possible d'utiliser la fonctionnalité de transition de domaine dynamique de SELinux pour basculer le label de sécurité du processus client, le domaine client, vers un nouveau contexte, s'il s'avère que c'est autorisé par la politique de sécurité. Le domaine client a besoin du droit setcurrent ainsi que du droit dyntransition de l'ancien domaine vers le nouveau domaine.

Les transitions de domaine dynamique doivent être considérées avec attention car elles permettent aux utilisateurs de basculer leur label, et du coup leur droits, quand ils le souhaitent, plutôt que (dans le cas d'une procédure de confiance) lorsque c'est demandé par le système. Du coup, le droit dyntransition est seulement considéré sûr quand il est utilisé pour basculer vers un domaine avec un plus petit ensemble de droits que le domaine original. Par exemple :

regression=# select sepgsql_getcon();
                    sepgsql_getcon
-------------------------------------------------------
 unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
(1 row)

regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c4');
 sepgsql_setcon
----------------
 t
(1 row)

regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c1023');
ERROR:  SELinux: security policy violation
   

Dans l'exemple ci-dessus, nous sommes autorisés à basculer du gros intervalle MCS c1.c1023 vers l'intervalle c1.c4 beaucoup plus petit. Par contre, la bascule inverse est interdite.

Une combinaison de transition de domaine dynamique et de procédure de confiance permet un cas d'utilisation intéressant qui correspond au cycle de vie typique d'un processus pour un logiciel de pooling de connexions. Même si votre pooler de connexions n'est pas autorisé à exécuter la plupart des commandes SQL, vous pouvez l'autoriser à basculer le label de sécurité du client en utilisant la fonction sepgsql_setcon() à l'intérieur d'une procédure de confiance. Après cela, cette session aura les droits de l'utilisateur cible plutôt que ceux du pooler de connexions. Le pooler de connexions peut ensuite annuler le changement du label de sécurité en utilisant de nouveau sepgsql_setcon() avec l'argument NULL, encore une fois en l'appelant à partir d'une procédure de confiance avec les droits appropriés. Le point ici est que seule la procédure de confiance a réellement le droit de modifier le label de sécurité en cours et ne le fait que si autorisé. Bien sûr, pour un traitement sécurisé, le stockage des autorisations (table, définition de procédure, ou autres) doit être protégé des accès non autorisés.

F.35.5.6. Divers

Nous rejetons la commande LOAD car tout module chargé pourrait facilement court-circuiter la politique de sécurité.

F.35.6. Fonctions Sepgsql

Tableau F.29 affiche la liste des fonctions disponibles.

Tableau F.29. Fonctions Sepgsql

sepgsql_getcon() returns text Renvoie le domaine client, le label de sécurité actuel du client.
sepgsql_setcon(text) returns bool Bascule le domaine client de la session actuelle sur un autre domaine, si cela est autorisé par la politique de sécurité. Cette fonction accepte aussi NULL en entrée comme demande de transaction vers le domaine original du client.
sepgsql_mcstrans_in(text) returns textTraduit l'intervalle MLS/MCS donné en un format brut si le démon mcstrans est en cours d'exécution.
sepgsql_mcstrans_out(text) returns textTraduit l'intervalle MCS/MCS brut donné en son format qualifié si le démon mcstrans est en cours d'exécution.
sepgsql_restorecon(text) returns bool Configure les labels de sécurité initiaux pour tous les objets à l'intérieur de la base de données actuelle. L'argument peut être NULL ou le nom d'un specfile à utiliser comme alternative du fichier système par défaut.

F.35.7. Limitations

Droits DDL

Dû aux restrictions d'implémentations, certaines opérations DDL ne vérifient pas les droits.

Droits DCL

Dû aux restrictions d'implémentations, les droits DCL ne vérifient pas les droits.

Contrôle d'accès au niveau ligne

PostgreSQL propose le contrôle d'accès au niveau ligne. Cependant, sepgsql ne le supporte pas.

Canaux cachés

sepgsql n'essaie pas de cacher l'existence d'un objet particulier, même si l'utilisateur n'est pas autorisé à y accéder. Par exemple, nous pouvons inférer l'existence d'un objet invisible suite à un conflit de clé primaire, à des violations de clés étrangèes et ainsi de suite, même si nous ne pouvons pas accéder au contenu de ces objets. L'existence d'une table secrète ne peut pas être caché. Nous ne faisons que verrouiller l'accès à son contenu.

F.35.8. Ressources externes

SE-PostgreSQL Introduction

Cette page wiki fournit un bref aperçu, le concept de la sécurité, l'architecture, l'administration et les fonctionnalités futures.

SELinux User's and Administrator's Guide

Ce document fournit une connaissance large pour administrer SELinux sur vos systèmes. Il cible principalement les systèmes d'exploitation Red Hat mais n'y est pas limité.

Fedora SELinux FAQ

Ce document répond aux questions fréquemment posées sur SELinux. Il cible principalement Fedora mais n'y est pas limité.

F.35.9. Auteur

KaiGai Kohei