mercredi 18 décembre 2024

Contraintes d'intégrité référentielle

 Considérons cet écran libreoffice:


Les données qui sont affichées proviennent de deux tables: la table 'employés' dont la colonne 'service' fait référence à la clef primaire 'service_id' d'une autre table, la table 'services'.
Le contenu de 'service' doit nécessairement être une valeur de la clef primaire 'service_id'. C'est l'intégrité référentielle. 'service' est une clef étrangère (foreign key).
Si les tables sont dans une base de données Postgresql, cette intégrité référentielle peut être garantie par une contrainte.
Par exemple si je tente de remplacer le service 06 de l'employés 1011 par le service 07 (qui n'existe pas) j'obtiens:


Mais on pourrait arriver au même résultat en se basant uniquement sur libreoffice. Ici le nom du service est affiché mais pas son code (06):


Et l'utilisation du menu déroulant me permet uniquement de remplacer le service du matricule 1011 par un  service existant:


Mais que se passe-t-il si je touche à la table 'services' ? Cette fois l'existence de la contrainte postgresql est essentielle pour assurer l'intégrité référentielle.
Si je tente de supprimer la rangée de clef 03 de la table 'services' je reçois ce message:


La suppression n'a pas lieu. Cependant si je regarde de plus près cette contrainte (employés_services_fkey) à l'aide de pgAdmin4, je constate que d'autres possibilité existent:




En cas de suppression (On delete) les actions le plus courantes sont:

SET NULL:
Pour tous les employés dont le code service est 03, ce code service est mis à NULL, si c'est permis.
NULL, ce n'est pas des espaces pour du texte, ni zéro pour un nombre.

CASCADE:
Tous les employés du service 03 sont supprimés

SET DEFAULT:
Si le code service d'un employé est 03, il est remplacé par sa valeur par défaut, si celle-ci existe et s'il lui correspond une rangée de la table 'services'.
Par exemple, cette valeur par défaut pourrait être 99, mais il faudrait aussi dans la table 'services' une rangée 99.

En cas d'update:

CASCADE
Le code service de tous les employés concernés est modifié

jeudi 28 novembre 2024

Postgesql Fedora: accès depuis le réseau

Je vais montrer comment accéder à une base de données postgresql depuis un poste client qui n'est pas sur la machine du serveur mais sur le même réseau. Tout d'abord dans le fichier postgresql.conf, dé-commenter et modifier la ligne listen_addresses:

listen_addresses = '*' # what IP address(es) to listen on;

Ensuite je m'occupe du fichier pg_hba.conf en ajoutant le lignes qui conviennent:

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer map=map01
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident map=map01
# IPv4 lan connections
host    all             all             192.168.1.0/24          ident map=map02
# IPv6 local connections:
host    all             all             ::1/128                 ident map=map01
# IPv6  lan connections
host    all             all             fe80::/10               ident map=map02

(en rouge ce qui est ajouté)

Puis j'adapte pg_ident.conf qui pourrait maintenant ressembler à:

# MAPNAME       SYSTEM-USERNAME         PG-USERNAME

map01 postgres postgres
map01 mifel michel
map01 mifel titi
map02           michel michel
map02 michel titi
map02 viviane titi

Les fichiers concernés se trouvent dans /var/lib/pgsql/data. J'utilise sudo nano pour procéder.

En ce qui concerne le pare-feu, les commandes à lancer sont:

mifel@fedora:~$ sudo firewall-cmd --permanent --add-rich-rule 'rule family="ipv4" source address="192.168.1.0/24" service name="postgresql" accept'
mifel@fedora:~$ sudofirewall-cmd --permanent --add-rich-rule 'rule family="ipv6" source address="fe80::/10" service name="postgresql" accept'
mifel@fedora:~$ sudo firewall-cmd --reload

Le service postgresql ouvre le port 5432:

mifel@fedora:~$ firewall-cmd --permanent --service=postgresql --get-ports
5432/tcp

La commande hostnamectl m'informe que le nom 'hostname' n'est pas défini de manière statique: j'y remédie:

mifel@fedora:~$ sudo hostnamectl hostname fedora

Pour les connexions réseau je pouvais choisir dans pg_hba.conf une identification par mot de passe, mais j'ai préféré garder ident.
Donc je dois maintenant sur chaque poste client installer et activer oidentd (voir post précédent) 

Ensuite pour le pare-feu:

michel@arcturus:~$ sudo firewall-cmd --permanent --add-rich-rule 'rule family="ipv4" source address="192.168.1.0/24" service name="ident" accept'
michel@arcturus:~$ sudo firewall-cmd --permanent --add-rich-rule 'rule family="ipv6" source address="fe80::/10" service name="ident" accept'
michel@arcturus:~$ sudo firewall-cmd --reload

Le port 113 est maintenant ouvert:

michel@arcturus:~$ firewall-cmd --permanent --service=ident --get-ports
113/tcp

Et voilà:



dimanche 24 novembre 2024

Postgresql Fedora: démarrer

Postgresql est puissant gestionnaire de base de données, mais le démarrage de cet outil pose parfois certains problèmes. Je vais expliquer comment les résoudre.  

Il s'agit en premier de sélectionner le paquet qui convient. Dans Fedora le paquet 'postgresql' donnera seulement le client. Il faut donc installer le paquet 'postgresql-server', ce qui provoquera par entrainement l'installation du paquet 'postgresql'. Je procède en ligne de commande (dans un terminal):

mifel@fedora:~$ sudo dnf install postgresql-server

Puis

mifel@fedora:~$ sudo /usr/bin/postgresql-setup --initdb
mifel@fedora:~$ sudo systemctl start postgresql
mifel@fedora:~$ sudo systemctl enable postgresql
mifel@fedora:~$ 

Ensuite je passe à l'étape de la création d'un utilisateur postgresql.
Seul l'utilisateur postgres peut créer un nouvel utilisateur. Le problème est de devenir pour un temps postgres:

mifel@fedora:~$ sudo su postgres
[sudo] Mot de passe de mifel : 
bash-5.2$ whoami
postgres
bash-5.2$ createuser -d -r michel
bash-5.2$ exit
exit
mifel@fedora:~

Le retour de la commande whoami montre bien que je suis devenu postgres. En tant que tel, je crée l'utilisateur michel, qui peut créer des bases de données et d'autres utilisateurs. Puis je redeviens mifel. 
Je tente ensuite de créer la base de données bd01:

mifel@fedora:~$ createdb bd01
createdb: erreur : la connexion au serveur sur le socket « /var/run/postgresql/.s.PGSQL.5432 » a échoué : FATAL:  le rôle « mifel » n'existe pas
mifel@fedora:~$ createdb bd01 -U michel
createdb: erreur : la connexion au serveur sur le socket « /var/run/postgresql/.s.PGSQL.5432 » a échoué : FATAL:  authentification peer échouée pour l'utilisateur « michel »
mifel@fedora:~

Le plus simple aurait été bien sûr de créer mifel lorsque j'étais postgres. Mais comme mifel n'existe pas dans postgresql, il faut qu'il puisse se connecter en tant que michel. Je modifie en conséqence le fichier /var/lib/pgsql/data/pg_hba.conf (par exemple avec sudo nano /var/lib/pgsql/data/pg_hba.conf):

# "local" is for Unix domain socket connections only
local   all             all                                     peer    map=map01
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident   map=map01
# IPv6 local connections:
host    all             all             ::1/128                 ident   map=map01

(en rouge, ce qui a été ajouté)

De même à la fin du fichier /var/lib/pgsql/data/pg_ident.conf, j'ajoute les lignes qui définissent map01:

# MAPNAME       SYSTEM-USERNAME         PG-USERNAME
map01           postgres                postgres
map01           mifel                   michel
map01           mifel                   titi

Pour finir je redémarre posgresql:

mifel@fedora:~$ sudo systemctl restart postgresql
[sudo] Mot de passe de mifel : 
mifel@fedora:~$ 

Je peux maintenant créer la base de données bd01 et l'utilisateur titi.
En images:

Utilisant psql, je me connecte à bd01 en tant que titi:


Toutes les connexions ont été jusqu'à présent effectuées via le socket unix. Mais dans le cas d'une connexion via la boucle locale, le processus d'authentification s'effectue avec ident comme indiqué dans le fichier pg_hba.conf.
Pour tester je force psql à passer par la boucle locale:

mifel@fedora:~$ psql -h localhost bd01 titi
psql: erreur : la connexion au serveur sur « localhost » (::1), port 5432 a échoué : FATAL:  Échec de l'authentification Ident pour l'utilisateur « titi »
mifel@fedora:~$ 

Ça ne fonctionne plus !

En fait il faut installer oidentd:

mifel@fedora:~$ sudo dnf install oidentd

Puis

mifel@fedora:~$ sudo systemctl start oidentd.socket
mifel@fedora:~$ sudo systemctl enable oidentd.socket
mifel@fedora:~$ 

Et maintenant ça fonctionne:


Dans un prochain article je traiterai des connexions depuis un poste client situé sur une autre machine. 


lundi 6 novembre 2023

Presse-papier dans linux mint

Il semblerait que beaucoup de personne se plaigne de l'absence d'un presse-papier dans Linux Mint Cinnamon.

Pourtant il existe l'applet gpaste rechargé qui nécessite évidemment que soit installé gpaste. Le problème est que l'applet continue à réclamer sont installation alors que gpaste est déjà installé. 

En fait il faut installer aussi gir1.2-gpaste et puis ça fonctionne.

Comme Linux Mint est basé sur Ubuntu, dans Ubuntu Cinnamon, ça se règle de la même façon.

Pour Fedora Cinnamon, pas de gir1.2-gpaste, mais on essaie quand même.

Catastrophe: Cinnamon se plante dès l'instant où on insère l'applet gpaste rechargé dans le tableau de bord. On tombe alors dans un mode de secours, où la possibilité est offerte de désactiver les applets. On refuse. Dans le mode de secours, le tableau de bord a disparu. On peut cependant faire apparaître des menus dans la partie supérieure gauche de l'écran. Il est alors possible de se déconnecter. A la reconnexion, miracle: tout fonctionne:



dimanche 5 novembre 2023

Disque externe bootable legacy et uefi

J'ai un disque dur externe usb que j'ai formaté de manière à ce qu'il puisse booter aussi bien de manière traditionnelle (legacy)  que en mode uefi:

toto@aldebaran:~$ sudo fdisk -l /dev/sda
[sudo] Mot de passe de toto: 
Disque /dev/sda : 447,13 GiB, 480103981056 octets, 937703088 secteurs
Disk model: 80G2G0A-00JH30  
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 4096 octets
taille d'E/S (minimale / optimale) : 4096 octets / 4096 octets
Type d'étiquette de disque : gpt
Identifiant de disque : 6B6A3B5A-81C8-479D-B261-B4733B4D0D70

Périphérique     Début       Fin  Secteurs Taille Type
/dev/sda1         2048      4095      2048     1M Amorçage BIOS
/dev/sda2         4096   2101247   2097152     1G Système EFI
/dev/sda3      2101248  18878463  16777216     8G Partition d'échange Linux
/dev/sda4     18878464 102764543  83886080    40G Système de fichiers Linux
/dev/sda5    102764544 186650623  83886080    40G Système de fichiers Linux
/dev/sda6    186650624 937701375 751050752 358,1G Système de fichiers Linux
michel@pc-linuxshop-A7K57UJU:~$ 

Grub s'installe dans sda1 dans le cas d'un amorçage en mode traditionnel, sda2 est monté dans /boot/efi pour un amorçage en mode UEFI.
J'ai installé un système linux (linux mint)  sur ce disque USB, à partir d'un laptop dont le boot est legacy.
Pas de souci lorsqu'il est branché sur un ordinateur qui s'amorce à l'ancienne. Par contre si ce disque dur externe est branché sur un ordinateur dont l'amorçage est UEFI, il n’apparaît pas dans la liste des périphériques sur les quels on peut booter.
Depuis un ordinateur UEFI où est installé Ubuntu (22.04), je lance les commandes suivantes:

sudo mount /dev/sda4 /mnt
sudo mount /dev/sda2 /mnt/boot/efi 
for i in /dev /dev/pts /proc /sys /run; do sudo mount -B $i /mnt/$i; done  
sudo mount --bind /sys/firmware/efi/efivars /mnt/sys/firmware/efi/efivars
sudo chroot /mnt
grub-install 
update-grub
exit  
sudo umount /dev/sda2
sudo umount /dev/sda4

(/dev/sda4 contient la racine de linx mint avec lequel je veux démarrer mon disque USB.)
Mais déception: ça ne fonctionne pas.
Le disque possède le drapeau pmbr_boot, ce qui pose problème.
Il faut enlever ce drapeau:

toto@aldebaran:~$ sudo parted /dev/sda
(parted) disk_set pmbr_boot off
(parted) quit

Et voilà, le problème est résolu. 

vendredi 1 septembre 2023

Blscfg et Fedora

Fedora utilise par défaut BLSCFG (Boot Loader Specification Configuration) comme on peut le vérifier dans le fichier /etc/defaults/grub qui contient GRUB_ENABLE_BLSCFG=true. De ce fait /boot/grub2/grub.cfg ne contient aucune entrée menuentry pour Fedora, mais seulement des entrées pour les autres systèmes d'exploitation.

Par contre on y trouve: 

insmod

blscfg

La commande blscfg ajoute des entrées au menu en se basant sur le contenu du dossier /boot/loader/entries. Ici le dossier contient 4 fichiers:

[toto@fedora ~]$ sudo ls -1 /boot/loader/entries 
7753b84a2ac148e7894de73d56d9be39-0-rescue.conf
7753b84a2ac148e7894de73d56d9be39-6.4.11-200.fc38.x86_64.conf
7753b84a2ac148e7894de73d56d9be39-6.4.12-200.fc38.x86_64.conf
7753b84a2ac148e7894de73d56d9be39-6.4.9-200.fc38.x86_64.conf

J'examine le contenu d'un des fichiers:

[toto@fedora ~]$ sudo -i
[sudo] Mot de passe de toto : 
[root@fedora ~]# cd /boot/loader/entries
[root@fedora entries]# cat 7753b84a2ac148e7894de73d56d9be39-6.4.12-200.fc38.x86_64.conf 
title Fedora Linux (6.4.12-200.fc38.x86_64) 38 (Workstation Edition)
version 6.4.12-200.fc38.x86_64
linux /boot/vmlinuz-6.4.12-200.fc38.x86_64
initrd /boot/initramfs-6.4.12-200.fc38.x86_64.img
options root=UUID=a7465ac8-7427-4c7b-a2f4-3b6dcb9fcfae ro resume=UUID=f17ebeb2-0767-4f7c-ba74-5ba3ed6acb92 rhgb quiet 
grub_users $grub_users
grub_arg --unrestricted
grub_class fedora
[root@fedora entries]# 

Pour une raison ou une autre, je veux ne pas utiliser blscfg. Donc dans /etc/defaults/grub je mets:

GRUB_ENABLE_BLSCFG=false

Ensuite je regénère grub.cfg avec la commande

[toto@fedora ~]$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg

Tout va bien jusqu'au prochain changement de noyau:
catastrophe: kernel panic
Il faut alors booter sur le noyau précédent pour réparer les dégâts. Si j’examine grub.cfg, je constate que dans la commande linux qui permet de booter sur le nouveau noyau se trouve:
root=/dev/sdb5 (dans mon cas) au lieu de root=UUID=.....
Pour régler le problème, il suffit de régénérer grub.cfg comme précédemment. Il n'est même pas nécessaire de rebooter: on peut procéder dès que l'update est terminé.


jeudi 24 février 2022

Substitution de variables d'environnement

Il existe un utilitaire qui permet la substitution de variables d'environnement: il s'agit de envsubst. Franchement, je ne connaissais pas cet utilitaire jusqu'à ce que je me heurte au problème suivant: substitution de variables dans une commande sed, lorsque le script avec les instructions de sed est un fichier (voir article précédent)

Expérimentons cet utilitaire. Tout d'abord je crée des variables d'environnement (dans un terminal):

export var1=Titine var2=Toto var3=Riri

Le mot export est nécessaire ou sinon on crée des variables du shell.

Ensuite je lance l'utilitaire en tapant envsubst suivi d'un appui sur ENTER.

Le curseur n'est pas après l'invite de commande: le système attend une action de ma part car envsubst renvoie vers la sortie standard (stdout), après traitement, le texte qui lui est fourni en entrée. Et rien ne lui est fourni. 

Allons-y! L'entrée standard est dans notre cas le clavier.

Je tape le texte 

$var2 aime $var1

suivi de ENTER pour envoyer. Aussitôt le retour apparaît à l'écran:


Je peux continuer à procéder, puis terminer avec CTRL-D, ce qui ramène le curseur après l'invite de commande:


Ce que j'ai tapé à l'écran je peux aussi le mettre dans un fichier appelé avant et lancer la commande:

envsubst < avant



Ici l'entée standard n'est plus le clavier, elle a été redirigée vers le fichier avant qui contient

$var2 aime $var1

mais $var3 aime aussi $var1

Je peux aussi créer le fichier après comme ceci:

envsubst < avant > après

Rien n’apparaît à l'écran puisque la sorte standard a été redirigée vers le fichier après.

Je peux aussi indiquer quelles sont les variables à considérer:


Cette fois var3 est ignoré.
Les variables à traiter peuvent même se trouver au sein d'un texte (appelé shell-format si on se réfère à man envsubst):


Ce texte peut se trouver dans un fichier.
Si le fichier sf-file contient par exemple

$var1 joue avec $var2

$var1 va au restaurant


la commande

envsubst "$(cat sf-file)" < avant

donnera le résultat escompté:


Avec l'option -v, envsubst donne la liste des variables qui seront retenues suite à l'utilisation d'un shell-format. L'entrée standard est ignorée. 
Exemple:



Avec cette commande:

envsubst -v "$(env | grep '^var' | sed 's/^/\$/')"

seules seront retenues les variables définies au début de ce billet: