Documentation PostgreSQL 14.22 » Annexes » Modules supplémentaires fournis » sepgsql

Précédent | Niveau supérieur | Suivant
F.36. seg | Sommaire | F.38. spi

## F.37. 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.37.7.

### F.37.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à fourni 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 quelle que 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.37.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ée 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 erreurs, vous pouvez commencer à lancer le serveur normalement.

### F.37.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.37.2. Notez que l'utilisateur du système d'exploitation doit être capable de se connecter à la base de données en tant que super-utilisateur 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. (Ce fichier Makefile est habituellement fourni avec le RPM `selinux-policy-devel` ou `selinux-policy`.) 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.37.4. Paramètres GUC

`sepgsql.permissive` (`boolean`)

  Ce paramètre active sepgsql pour qu'il fonctionne en mode permissif, quelle que soit la configuration du système. La valeur par défaut est off. Ce paramètre est 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 quelle que 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, quelle que soit la politique du système.

### F.37.5. Fonctionnalités

#### F.37.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.37.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 super-utilisateurs 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.37.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 leurs 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.37.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.37.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 leurs 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.37.5.6. Divers

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

### F.37.6. Fonctions Sepgsql

Tableau F.30 affiche la liste des fonctions disponibles.

Tableau F.30. Fonctions Sepgsql

Fonction Description
`sepgsql_getcon` () → `text` Renvoie le domaine client, le label de sécurité actuel du client.
`sepgsql_setcon` ( `text` ) → `boolean` 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` ) → `text` Traduit l'intervalle MLS/MCS donné en un format brut si le démon mcstrans est en cours d'exécution.
`sepgsql_mcstrans_out` ( `text` ) → `text` Traduit l'intervalle MCS/MCS brut donné en son format qualifié si le démon mcstrans est en cours d'exécution.
`sepgsql_restorecon` ( `text` ) → `boolean` 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.37.7. Limitations

Droits DDL

  À cause de restrictions d'implémentations, certaines opérations DDL ne vérifient pas les droits.

Droits DCL

  À cause de 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ères 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.37.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.37.9. Auteur

KaiGai Kohei `<kaigai@ak.jp.nec.com>`