Introduction
MarketLedger a besoin d'un rapport de règlement pour les vendeurs de son petit marché. Ce rapport doit lire les totaux de la veille, pas les adresses e-mail des clients ni les références bancaires, et ne doit pas modifier les commandes. Sa politique actuelle de création de comptes accorde plus de droits que cette tâche n'en exige.
Vous restreindrez cette politique, obtiendrez un véritable accès PostgreSQL temporaire via OpenBao et enregistrerez un rapport complet séparé par des tabulations à l'aide de la requête fournie. Des connaissances de base du terminal et des chemins suffisent. Les permissions SQL, les fichiers d'identifiants et les options de commande utiles sont expliqués avant utilisation ; aucun compte cloud ni programmation Python n'est nécessaire.
Découvrir la boutique et le rapport dont elle a besoin
Dans cette étape, vous commencerez par l'activité en fonctionnement et un rapport normal avant de modifier les permissions. Utilisez Terminal tout au long de ce TP. cd change de répertoire ; un chemin absolu fonctionne depuis n'importe où :
cd /home/labex/project/market-report
PostgreSQL est la base de données préparée. OpenBao est un service de secrets préparé qui peut demander à cette base de créer un nouvel accès pour une durée limitée. Ce sont de véritables processus dans le conteneur de ce TP. Il ne s'agit ni d'une base hébergée, ni d'un déploiement de secrets en production.
Le programme préparé shop.py est un petit client du service de boutique en fonctionnement. Son exécution ne nécessite pas d'écrire du Python. list affiche les commandes du jour :
python3 shop.py list
Au départ, une liste vide, [], est attendue. Passez une commande normale. --order identifie la commande, --vendor son vendeur et --cents indique le montant en nombre entier de centimes :
python3 shop.py place --order O201 --vendor V101 --cents 600
Vous devez obtenir une commande enregistrée et payée pour la date commerciale synthétique 2026-10-29. Si vous répétez la commande, le service refuse l'identifiant en double ; utilisez list pour voir la commande existante au lieu de la supprimer ou de l'écraser.
Le règlement couvre la date précédente, 2026-10-28. La nouvelle commande du jour ne doit pas modifier les totaux de la veille. cat affiche un fichier texte ; examinez le rapport d'exemple fonctionnel préparé :
cat demo.tsv
Trois lignes de vendeurs sont attendues :
vendor_id vendor_name paid_orders total_cents
V101 Birch Pantry 2 4700
V102 Elm Bakery 1 2000
V103 Maple Kitchen 1 2700
Les séparateurs sont des tabulations, d'où l'extension .tsv. Quatre commandes payées totalisent 9400 centimes. La commande Elm annulée est exclue. La démonstration a été lue avec un lecteur préparé distinct ; la copier ne démontre pas que votre nouvelle identité de base de données peut exécuter le rapport.
Une vue est une requête de base de données nommée qui expose certains résultats. reporting.daily_settlement joint les noms des vendeurs aux totaux des commandes payées et exclut les adresses e-mail des clients et les références bancaires. Les enregistrements d'origine restent dans les tables privées public.orders et public.vendors. Ici, reporting et public sont des noms de schémas regroupant des objets de base de données ; le mot public ne signifie pas que tous les rôles doivent y accéder.
Vous pouvez modifier role.sql, enregistrer le rôle OpenBao settlement-report, obtenir les identifiants de ce rôle et créer vos fichiers de rapport et d'identifiants. Gardez sans modification la boutique, les enregistrements d'origine de la base, l'autre rôle de rapport, la requête fournie, le fichier d'environnement, le jeton d'opérateur et l'environnement d'exécution préparé. Vous n'avez besoin ni d'un mot de passe d'administrateur de base de données, ni d'un jeton root OpenBao.
Pour une erreur ordinaire No such file or directory, revenez avec le cd absolu ci-dessus, utilisez ls pour vérifier les vrais noms des fichiers et réessayez. Ne réinitialisez pas l'environnement pour corriger une faute de frappe.
Limiter la politique de création de comptes à la vue de règlement
Dans cette étape, vous retirerez les permissions inutiles au rapport. Commencez dans Terminal, dans /home/labex/project/market-report.
Lisez les instructions actuelles de création de comptes :
cat role.sql
OpenBao remplace trois paramètres lors de l'émission d'identifiants : {{name}} devient un nouveau nom d'utilisateur de base de données, {{password}} un mot de passe généré et {{expiration}} l'heure d'expiration du compte. Conservez ces paramètres ; ne les remplacez pas par votre propre nom d'utilisateur ou mot de passe fixe.
CREATE ROLE ... WITH LOGIN crée un compte de connexion PostgreSQL. VALID UNTIL limite la période pendant laquelle son mot de passe peut authentifier une nouvelle connexion. Cela ne ferme pas toutes les connexions déjà ouvertes. Vous étudierez la révocation explicite et l'expiration naturelle des baux dans le prochain TP guidé.
GRANT accorde une permission. USAGE ON SCHEMA reporting permet de rechercher les objets de ce schéma. SELECT ON reporting.daily_settlement permet de lire cette seule vue. Les droits supplémentaires actuels sur public permettent de lire les tables privées et de modifier les commandes ; ce rapport n'a besoin ni de l'un ni de l'autre.
La dernière ligne ALTER ROLE ... SET log_statement = 'all' active l'audit SQL natif pour chaque compte de rapport nouvellement créé. Conservez-la : les requêtes effectuées sous cette identité doivent rester attribuables. Les instructions de gestion créant les comptes, qui contiennent des mots de passe, ne sont pas journalisées par ce réglage propre à chaque compte. Le journal d'audit OpenBao préparé hache également les valeurs secrètes.
Remplacez le fichier par les instructions plus restreintes ci-dessous. cat > role.sql redirige le texte fourni vers ce fichier. <<'ROLESQL' commence un here-document ; le marqueur entre apostrophes préserve exactement le texte inclus jusqu'à la ligne contenant uniquement ROLESQL :
cat > role.sql <<'ROLESQL'
CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';
GRANT USAGE ON SCHEMA reporting TO "{{name}}";
GRANT SELECT ON reporting.daily_settlement TO "{{name}}";
ALTER ROLE "{{name}}" SET log_statement = 'all';
ROLESQL
Relisez-le :
cat role.sql
Le rôle possède un accès généré, une durée de validité du mot de passe limitée, une permission de recherche dans le schéma et un accès en lecture à une seule vue. Il ne dispose d'aucun accès aux tables brutes, droit d'écriture ou attribut d'administration. Une permission sur une vue est utile ici parce que la vue fournie omet volontairement les données privées ; une vue exposant ces champs privés n'offrirait pas la même séparation.
Si le terminal attend davantage de saisie parce que vous avez omis le marqueur final, saisissez ROLESQL seul sur une ligne. Si le fichier enregistré est incomplet, répétez le bloc entier. Cela ne modifie que votre fichier de politique, pas encore la base en fonctionnement.
Enregistrer la politique avec l'opérateur OpenBao restreint
Dans cette étape, vous enregistrerez votre politique de comptes sans utiliser une identité d'administration du service de secrets. Restez dans Terminal.
Lisez le fichier d'environnement préparé avant de le charger :
cat env.sh
source env.sh exécute ces affectations dans le shell courant de ce terminal. export rend une valeur accessible aux commandes enfants. Le fichier ajoute l'outil préparé bao à PATH, la liste de recherche des commandes du shell, et définit les adresses locales d'OpenBao et de PostgreSQL. $(cat ...) lit le jeton d'opérateur préparé depuis son fichier privé ; le jeton lui-même n'est pas affiché. Ces réglages appartiennent à cette session de terminal. Un nouveau terminal doit les charger à nouveau :
source env.sh
Un jeton d'opérateur OpenBao autorise les requêtes vers le service de secrets. Ce n'est ni un nom d'utilisateur, ni un mot de passe PostgreSQL. Ce jeton peut gérer et obtenir les identifiants de settlement-report et révoquer les baux précis de ce rôle. Il ne peut pas lire la connexion de gestion de la base ni gérer le rapport d'inventaire distinct.
bao write écrit une configuration au chemin OpenBao nommé. db_name=market sélectionne la connexion préparée à la base. creation_statements=@role.sql lit votre fichier SQL comme valeur de ce champ ; @ est la syntaxe d'entrée depuis un fichier d'OpenBao. default_ttl=10m donne par défaut dix minutes aux nouveaux baux et max_ttl=15m plafonne leur configuration de durée de vie. TTL désigne une durée de vie. Utilisez ces limites courtes pour le rapport plutôt que des heures ou un compte sans limite :
bao write database/roles/settlement-report db_name=market creation_statements=@role.sql default_ttl=10m max_ttl=15m
Vous devez obtenir une confirmation d'écriture dans database/roles/settlement-report. Cela modifie la politique de création ; aucun accès de base de données n'a encore été émis. Une modification de politique affecte les futurs comptes. Elle ne retire pas les permissions d'un accès déjà émis. Après toute modification de politique enregistrée, obtenez de nouveaux identifiants et régénérez votre rapport avec ceux-ci. Le contrôle final exige que l'identité du rapport ait été émise après votre dernier enregistrement de politique. Ne laissez pas actif un ancien accès de rapport trop permissif ; la procédure de reprise conditionnelle de l'étape suivante indique comment mettre fin à son bail précis avant de remplacer son fichier d'identifiants.
L'autocontrôle de politique lit la politique enregistrée actuelle et exerce son SQL dans un environnement PostgreSQL jetable. Il n'émet pas de bail, ne modifie pas la base réelle et n'exécute pas votre rapport réel. sudo permet à ce contrôleur préparé d'inspecter la configuration protégée et d'exécuter son compte ordinaire isolé ; vos commandes OpenBao et de base de données habituelles utilisent les identités restreintes :
sudo python3 /opt/labex-report/verify.py policy
S'il signale une permission supplémentaire ou une expiration manquante, corrigez role.sql et enregistrez-le à nouveau. Conservez les paramètres de substitution et la clause d'audit. Des instructions de permission équivalentes mettant en œuvre les limites indiquées sont acceptées ; le contrôle n'exige ni éditeur particulier, ni formulation SQL précise.
Obtenir des identifiants temporaires et exécuter le véritable rapport
Dans cette étape, vous utiliserez une identité de base de données nouvellement émise pour produire votre fichier de règlement. Commencez dans la même session Terminal, avec env.sh chargé.
Une réponse d'identifiants contient trois éléments distincts : un identifiant de bail qui identifie cette émission dans OpenBao, un nom d'utilisateur PostgreSQL généré et son mot de passe. Le jeton d'opérateur de l'étape précédente a autorisé l'émission ; il ne fait pas partie de ces identifiants de base de données.
Gardez les fichiers d'identifiants privés. umask 077 rend les nouveaux fichiers lisibles et modifiables uniquement par votre compte ; il ne modifie pas les fichiers existants :
umask 077
bao read demande des identifiants pour le rôle. -format=json choisit une sortie JSON structurée. > enregistre cette sortie dans lease.json, en remplaçant un fichier existant portant ce nom. Cette commande crée réellement un nouvel accès PostgreSQL et démarre le décompte de son bail ; ne la répétez pas simplement pour inspecter le même bail :
bao read -format=json database/creds/settlement-report > lease.json
jq sélectionne les champs JSON. -r affiche les chaînes sans guillemets JSON. Lisez l'identité non secrète, l'identifiant et la durée du bail ; n'affichez pas le mot de passe :
jq '.lease_id, .lease_duration, .data.username' lease.json
Vous devez obtenir un identifiant de bail database/creds/settlement-report/..., une durée de 600 secondes et un nom d'utilisateur généré. Leurs suffixes aléatoires diffèrent à chaque fois.
Le client PostgreSQL psql lit PGUSER et PGPASSWORD dans l'environnement. Les substitutions $(...) entre guillemets les définissent à partir de cette émission. Ces valeurs restent dans cette session de terminal et ses commandes enfants :
export PGUSER="$(jq -r .data.username lease.json)"
export PGPASSWORD="$(jq -r .data.password lease.json)"
psql -X ignore les personnalisations personnelles de démarrage de psql, -v ON_ERROR_STOP=1 arrête sur les erreurs SQL et -c fournit une commande SQL. SELECT current_user demande à PostgreSQL quelle identité cette connexion utilise réellement :
psql -X -v ON_ERROR_STOP=1 -c 'SELECT current_user;'
Vous devez obtenir le même nom d'utilisateur généré que dans lease.json, pas le compte d'écriture de la boutique, le lecteur de démonstration ou l'administrateur de la base.
Le fichier préparé report.sql sélectionne les quatre colonnes publiques du rapport, trie les lignes par identifiant de vendeur et les copie sur la sortie standard sous forme de données séparées par des tabulations avec un en-tête. Gardez la requête inchangée. -f lit le SQL dans ce fichier, tandis que > enregistre uniquement la sortie du rapport :
psql -X -v ON_ERROR_STOP=1 -f report.sql > settlement.tsv
Lisez votre résultat réel :
cat settlement.tsv
Ses trois lignes de vendeurs doivent correspondre à l'exemple métier précédent : Birch 2 / 4700, Elm 1 / 2000, Maple 1 / 2700. Aucune adresse e-mail de client ni référence bancaire ne doit apparaître. Le total reste de 9400 centimes parce que la commande O201 du jour n'entre pas dans le règlement de la veille.
Si une connexion ultérieure échoue avec password authentication failed, le bail de dix minutes a peut-être expiré pendant votre lecture. Il s'agit d'un échec d'identifiants, pas d'un refus de requête sur une table. Répétez une fois la commande d'émission d'identifiants, rechargez PGUSER et PGPASSWORD à partir du nouveau fichier, puis relancez les commandes d'identité et de rapport. Un nouveau nom d'utilisateur est attendu. Ne modifiez pas le nom d'utilisateur enregistré et ne prolongez pas manuellement l'expiration.
Une autre procédure de reprise s'applique si vous avez modifié la politique après avoir déjà émis des identifiants. Ce compte antérieur conserve ses droits d'origine. Avant de remplacer son lease.json, exécutez bao lease revoke "$(jq -r .lease_id lease.json)". La substitution entre guillemets fournit exactement l'identifiant du bail enregistré ; ce n'est ni un nom d'utilisateur de base de données, ni un préfixe de bail. Ne révoquez jamais le rapport d'inventaire ni tout un préfixe de baux. Après avoir mis fin à l'émission précédente, demandez de nouveaux identifiants, rechargez les deux variables de base de données et régénérez le rapport avec les commandes ci-dessus. Vous éviterez ainsi qu'un ancien accès trop permissif reste utilisable à côté du nouvel accès limité.
Confirmer que les données privées et les écritures restent inaccessibles
Dans cette étape, vous testerez les limites du compte tout en préservant la boutique et ses données d'origine. Utilisez le même Terminal avec votre identité PostgreSQL émise.
La lecture suivante doit échouer. SELECT * demande toutes les colonnes ; la politique doit arrêter ce compte avant qu'il puisse lire les commandes brutes :
psql -X -v ON_ERROR_STOP=1 -c 'SELECT * FROM public.orders;'
Une erreur PostgreSQL permission denied pour le schéma privé ou la table est attendue. $? est le code de sortie de la commande immédiatement précédente ; echo l'affiche. Lisez-le immédiatement :
echo $?
Le résultat attendu est 1, indiquant une requête SQL refusée. Un échec de connexion avec le code 2 ne démontre pas cette limite de permissions ; utilisez la procédure de réémission et de rechargement de l'étape précédente si le bail a expiré.
Essayez maintenant une écriture sans danger pour les données : UPDATE ... WHERE false ne correspond à aucune ligne et ne pourrait donc pas modifier les commandes, même si le compte avait à tort des privilèges excessifs. Elle doit néanmoins être refusée pour permission insuffisante :
psql -X -v ON_ERROR_STOP=1 -c 'UPDATE public.orders SET amount_cents = 0 WHERE false;'
echo $?
Une erreur de permission et le code 1 sont à nouveau attendus. Le compte peut lire la vue prévue, mais ne peut ni lire les données privées brutes, ni modifier les commandes.
Le client de boutique préparé utilise l'identité d'écriture distincte du service de boutique, plutôt que vos identifiants de rapport. Confirmez que la commande que vous avez passée reste disponible :
python3 shop.py list
Exécutez le contrôle final en lecture seule. Il lit d'abord les éléments natifs existants d'émission OpenBao et de requêtes PostgreSQL, puis vérifie votre véritable rapport et les données métier préservées. Il ne crée pas d'accès manquant et ne génère pas le rapport à votre place :
sudo python3 /opt/labex-report/verify.py result
Vous disposez maintenant d'un règlement complet produit avec une véritable identité de base de données limitée et émise dynamiquement. Le prochain TP indépendant commence avec la bonne politique de permissions et se concentre sur la fin de l'accès et l'observation d'échecs de nouvelles connexions.
Résumé
Vous avez enregistré une politique limitée de création de comptes, obtenu de nouveaux identifiants PostgreSQL via un opérateur OpenBao restreint et utilisé cette identité pour enregistrer un véritable règlement. Sa vue expose les totaux métier nécessaires, tandis que les tables privées, les écritures et les privilèges d'administration restent hors du périmètre du rapport.
Le jeton d'opérateur, l'identifiant de bail et les identifiants de base de données ont des fonctions distinctes. Cet exercice dépend encore de composants de gestion préparés et fiables ; les comptes temporaires ne suppriment pas cette confiance initiale. Le TP suivant examine la révocation d'un bail précis, l'expiration naturelle et la reprise grâce à une nouvelle émission.


