Travail final
- Après les études de cas
- environ 3 h
Ce que vous saurez faire
Appliquez chaque module du cours à un service que vous n’avez pas créé dans ce cours. Ajoutez la connexion et le contrôle d’accès pour deux organisations à l’assistant documentaire de Larkfield. Larkfield et Bramble Books pourront ainsi le partager de façon sûre. Ensuite, prouvez avec des tests et des exécutions enregistrées que le service sait qui l’appelle. Il doit décider sur le serveur ce que cette personne peut faire, et dans quelle organisation. Il doit refuser tout accès entre organisations et mettre fin à l’accès quand il le faut. Enfin, adaptez la conception à un vrai fournisseur d’identité.
Avant de commencerCe qu’il faut savoir et avoir sous la main
- Vous avez terminé les modules 1 à 6. Chaque partie ci-dessous nomme les leçons qu’elle utilise.
- Vous n’avez pas besoin des études de cas pour ce travail. Le certificat exige au moins une étude de cas.
- Le service : votre
docs-assistantdu travail final de Bases de données et stockage pour les applications d’IA. Si vous ne l’avez pas, construisez d’abord son petit noyau : des documents avec versions, niveau d’accès et fichier; des questions avec réponses et citations; et une route de recherche. Vous n’avez pas besoin ici d’optimiser les index ni de faire l’exercice de restauration de ce travail. - Le projet du cours, comme source de code : votre
ticket-apià la fin du module 6, ou l’instantanéend-of-m06du dépôt des ateliers (Instantanés de ticket-api). Vous pouvez en copier du code : le fournisseur d’exerciceidp/,ticket_api/auth.py,access.py,tenancy.py, les scripts et les fonctions auxiliaires de test. Indiquez dans votre rapport ce que vous avez copié et modifié. Ne copiez pas ses routes, données ou tests pour simplement les renommer : le réviseur cherche les décisions propres à ce service. - Docker avec PostgreSQL 18 et pgvector, ainsi qu’Azurite, comme dans le cours. Aucun compte ni paiement n’est nécessaire. Un vrai fournisseur d’identité est facultatif (partie 4).
- Chaque tentative de ce travail vise votre propre service d’exercice, sur votre ordinateur, avec des personnes et des données fictives.
- Vous pouvez faire le travail en plusieurs séances. Exécutez les tests après chaque changement.
La situation : un assistant, deux commerces
Section intitulée « La situation : un assistant, deux commerces »Bramble Books utilise maintenant le service de soutien de Larkfield et veut aussi l’assistant documentaire. Ines téléversera les politiques de Bramble, et son personnel posera des questions à leur sujet. Kwame pose ses trois questions sur le nouveau service : « Qui appelle? Que peut faire cette personne? Dans quelle organisation? » Aujourd’hui, docs-assistant ne répond à aucune de ces questions. Toute personne qui peut y accéder peut lire tous les documents, même les limites de remboursement réservées au personnel de Larkfield.
Le service conserve sa propre base de données, docs, et son propre dossier, ~/projects/docs-assistant. Après ce travail :
- Deux organisations le partagent :
larkfieldetbramble. Chacune possède ses propres documents, fichiers, segments, questions et réponses. - Les mêmes personnes fictives se connectent : Grace, Sam, Omar, Camille, Ines, Tomás et Kwame. Leurs adhésions sont celles de
data/identity/memberships.csvdansticket-api. Camille fait partie du personnel de Larkfield et a un accès en lecture seule chez Bramble Books. Tomás n’a aucune adhésion. Kwame est administrateur de la plateforme et n’est membre d’aucun commerce. - Trois rôles par adhésion, avec au moins les règles suivantes. Un membre
read_only(lecture seule) pose des questions, lit les documents publics et lit seulement ses propres questions. Un membrestaff(personnel) lit aussi les documents réservés au personnel, téléverse des documents et lit toutes les questions de l’organisation. Un membreowner(propriétaire) peut aussi retirer des documents, gérer les membres et lire le journal d’audit. Rédigez vous-même la matrice complète et ajoutez une règle si votre service en a besoin. - Sa propre audience. Un jeton pour
docs-assistantn’est pas un jeton pourticket-api, et inversement.
Vos données. Les documents de Larkfield sont les 36 fichiers Markdown dans data/source/documents/ de ticket-api; 6 sont réservés au personnel. Ceux de Bramble sont les 3 documents de data/bramble/documents.csv; supplier-terms est réservé au personnel. Créez vos questions et réponses pour les deux commerces avec un script qui utilise une graine fixe. Toutes les personnes et les données sont fictives : indiquez-le dans votre rapport.
Partie 1 : contexte d’identité validé
Section intitulée « Partie 1 : contexte d’identité validé »Utilise OAuth et OIDC, Flux d’application, Lire un jeton : JWT, signatures et clés, Ce que signifie un jeton et Configuration du fournisseur.
- Copiez
idp/dans votre projet. Modifiez votre copie pour que ses jetons d’accès nommentdocs-assistantcomme audience. Enregistrez vos propres clients : un client en ligne de commande avec PKCE et, si vous créez une connexion par navigateur, un client Web. Exécutez le fournisseur sur le port 8401 pour éviter un conflit avec celui de l’API de billets. Notez qu’une vraie entreprise utilise un seul fournisseur pour les deux services. Expliquez dans la partie 4 comment un vrai fournisseur distingue les deux audiences. - Vérifiez chaque jeton d’accès sur le serveur : la signature avec les clés publiées (JWKS), mises en cache, et une liste d’autorisation d’algorithmes; l’émetteur; l’audience
docs-assistant;expetnbfavec une petite tolérance; et le type de jeton. Nommez la vérification qui refuse chaque mauvais jeton, comme le fait l’en-têteX-Token-Checkdu cours. - Ajoutez
GET /v1/me. Cette route renvoie l’identifiant utilisateur de la personne qui appelle, les portées du jeton et les adhésions. Le service lit les adhésions dans sa propre table, jamais dans le jeton. - Choisissez vos portées, par exemple
docs:read docs:write members:manage, et indiquez celles que chaque route exige. Un script de production de rapports qui demande seulementdocs:readne peut pas téléverser. - Le jeton ne contient ni organisation ni rôle. Si vous pensez les ajouter, écrivez un paragraphe sur les conséquences du retrait d’un membre.
Partie 2 : règles de rôles et de ressources appliquées sur le serveur
Section intitulée « Partie 2 : règles de rôles et de ressources appliquées sur le serveur »Utilise Utilisateurs et organisations, L’autorisation dans l’API, Requêtes sûres pour chaque locataire, Accès aux fichiers et à la récupération, Contexte d’identité des tâches et Opérations privilégiées.
- Ajoutez
tenant_idà chaque table contenant les données d’une organisation, avec des clés étrangères composites. Ainsi, une citation ne peut pas pointer vers un segment d’une autre organisation. La clé d’un document inclut l’organisation : les deux commerces peuvent avoir unreturns-policy. - Déplacez chaque route des données d’une organisation sous
/v1/tenants/{tenant}/. Exécutez les vérifications dans l’ordre du cours : identité (401), adhésion (404), rôle, puis portée (403), puis recherche dans l’organisation (404). Une personne externe reçoit le même 404 pour une organisation réelle ou fictive. - Écrivez la matrice d’accès deux fois : en texte, dans
docs/access-matrix.md, et en code, dans une seule fonctiondecide(). Écrivez un test qui compare les deux. - Faites de l’organisation un argument nommé obligatoire de chaque fonction du dépôt. Ajoutez la sécurité au niveau des lignes comme second verrou, avec un rôle qui n’est pas un superutilisateur. Sinon, expliquez pourquoi vous ne l’avez pas fait.
- Transmettez l’organisation et le niveau d’accès partout où des données quittent les tables : recherche documentaire et requête vectorielle (un filtre dans la même instruction), citations d’une réponse, liens de fichiers signés (vérifiez d’abord, signez ensuite) et chaque clé de cache.
- Ajoutez une tâche en arrière-plan, par exemple le découpage d’un document téléversé ou l’exportation des questions d’une organisation. Enregistrez l’acteur et l’organisation provenant de la requête vérifiée, puis vérifiez les deux à nouveau au lancement de la tâche.
- Enregistrez un événement d’audit pour chaque décision qui modifie des données et pour chaque refus : acteur, organisation (seulement pour le refus d’un membre), action, résultat et raison. Jamais de jeton ni de secret.
Partie 3 : tests négatifs entre organisations
Section intitulée « Partie 3 : tests négatifs entre organisations »Utilise Exemples de menaces, Tests négatifs et Auditabilité.
- Écrivez une matrice de tests : chaque personne, dans les deux organisations, sur chaque route protégée, avec le statut attendu par
decide(). Ajoutez les cas d’identité non valide sur chaque route : aucun jeton, jeton expiré, mauvaise audience, jeton d’identité et portée insuffisante. - Ajoutez les cas au niveau des objets : un membre utilise son propre chemin avec un identifiant réel de l’autre commerce. Faites-le pour un document, un fichier, une question et une tâche. Chaque réponse doit être le « n’existe pas » d’un identifiant absent.
- Écrivez manuellement des tests pour les règles qui dépendent des données, pas seulement du rôle. Par exemple, Omar lit ses propres questions, mais pas celles de Sam. Une recherche en lecture seule ne cite jamais un document réservé au personnel.
- Écrivez un script de tentatives, comme
scripts.attempts, avec au moins 8 tentatives fictives. Incluez un en-tête d’organisation falsifié, un jeton de l’API de billets et Camille utilisant son rôle de personnel chez Bramble Books. Le script doit se terminer par0 of N attempts got what they should not get.(aucune des N tentatives n’a obtenu ce qu’elle ne devait pas obtenir). - Générez le rapport de tests à partir des résultats JUnit de pytest, comme le fait
scripts.matrix_report. Une vérification ignorée ne compte jamais comme réussie. - Introduisez volontairement trois bogues dans votre service et montrez ce qui détecte chacun : une route qui demande la mauvaise action, une mauvaise règle dans
decide()et une requête sans son organisation. Retirez chaque bogue après son exécution et indiquez que les trois sont construits.
Partie 4 : conception du cycle de vie des jetons et des sessions adaptée à un vrai fournisseur
Section intitulée « Partie 4 : conception du cycle de vie des jetons et des sessions adaptée à un vrai fournisseur »Utilise Choix de session dans le navigateur, Cycle de vie d’une session, Configuration du fournisseur, Changements de cycle de vie et Remise du travail.
- Écrivez les durées de validité : jeton d’accès, tolérance, jeton de renouvellement et sa rotation, limites d’inactivité et absolue de la session du navigateur. Justifiez chaque nombre. Si votre service n’a pas de connexion par navigateur, concevez quand même la session et indiquez qu’elle n’est pas réalisée.
- Pour chaque endroit où une autorisation existe, dites si vous empêchez ou limitez dans le temps l’accès périmé, et pour combien de temps. Incluez l’adhésion, le jeton, la session, les réponses en cache, les tâches en attente et, le cas échéant, les invitations ou l’accès de soutien. Mesurez au moins un cas : retirez un membre, puis notez quand sa prochaine requête reçoit 404 et ce que son jeton permet encore d’obtenir.
- Écrivez les étapes de rotation des clés de votre fournisseur : publiez la nouvelle clé, signez ensuite avec elle, puis retirez l’ancienne. Expliquez ce qui arrive à un jeton signé avec une clé que le service n’a pas encore récupérée.
- Adaptez la conception à un vrai fournisseur dans
docs/identity-config.md. Utilisez Keycloak dans Docker, comme dans Configuration du fournisseur, ou Microsoft Entra ID à partir de sa documentation. Pour chaque paramètre, donnez le nom utilisé par le fournisseur : émetteur, audience, noms des portées, type de jeton, revendication (claim) qui contient l’identifiant stable de la personne et déconnexion. Écrivez le niveau de preuve à côté de chaque fournisseur : testé, testé une fois ou décrit, non testé. - Écrivez
docs/handoff.md: les choix encore ouverts, chacun avec la personne qui doit décider. Exemples : qui gère les adhésions quand deux services en ont besoin, combien de temps conserver le journal d’audit et s’il faut garder les questions d’un membre retiré.
Les cas d’échec à vérifier
Section intitulée « Les cas d’échec à vérifier »Un parcours réussi ne suffit pas. Montrez chacun de ces cas avec un test ou une exécution enregistrée, et précisez lequel. Chaque tentative vise votre propre service d’exercice, avec des données fictives.
- Aucun jeton, un jeton expiré, un jeton pour
ticket-api, un jeton d’identité,alg: noneet un jeton signé avec une autre clé reçoivent chacun 401, avec le nom de la vérification responsable du refus. Aucun de ces jetons ne figure dans votre journal d’audit. - Tomás demande une organisation réelle et une organisation fictive. Les deux corps de réponse 404 sont identiques, sauf l’identifiant de requête (
cmpou un test). - Sam demande un identifiant réel de document Bramble par le chemin de Larkfield. La réponse est identique à celle d’un identifiant qui n’existe pas.
- Omar téléverse un document (403) et cherche les limites d’approbation des remboursements de Larkfield : aucun document réservé au personnel dans les résultats ou les citations. Camille obtient seulement les documents publics de Bramble.
- Un en-tête
X-Tenant-IDfalsifié ou une organisation dans le corps de la requête ne change rien. - Le service crée un lien de fichier signé seulement après les vérifications. Ce même lien ne fonctionne plus après son expiration.
- Le rôle d’un membre change, ou le membre est retiré, avant l’exécution de sa tâche : le processus refuse la tâche et enregistre la raison. Une ligne de tâche falsifiée pour une autre organisation (construite) est aussi refusée.
- Une requête qui oublie son organisation (construite) renvoie seulement les lignes de la personne qui appelle grâce à la sécurité au niveau des lignes. Sinon, sans cette protection, un test échoue. Précisez le cas.
- Grace retire Camille de Larkfield. La prochaine requête de Camille dans cette organisation reçoit 404. Son accès à Bramble fonctionne encore, et son jeton permet encore d’obtenir une réponse de
/v1/me. - Quand PostgreSQL est arrêté, votre rapport de tests indique que les vérifications n’ont pas été exécutées et se termine avec une erreur.
Exécution dans un environnement neuf
Section intitulée « Exécution dans un environnement neuf »Avant de remettre votre travail, prouvez que le projet fonctionne à partir de zéro sur votre ordinateur :
- Copiez le projet dans un nouveau dossier, sans
.venv,.env,.idp,.tokensetreports. - Supprimez la base de données et les fichiers avec
docker compose down --volumes, puis redémarrez-les. - Créez un nouvel environnement virtuel, installez les dépendances de
requirements.txtet créez.envà partir de.env.example. Créez les clés et les secrets du fournisseur (python -m idp initdans votre copie). - Appliquez les migrations, chargez les deux commerces et exécutez tous les tests.
- Démarrez le fournisseur et le service. Exécutez votre script de tentatives, générez le rapport de tests et lancez votre vérification des jetons et secrets dans le journal d’audit.
Collez les commandes et leurs sorties dans votre rapport. Si une étape exige quelque chose qui manque au README, corrigez le README et exécutez les étapes à nouveau.
Ce qu’il faut remettre
Section intitulée « Ce qu’il faut remettre »Votre dossier docs-assistant (sans .env, .venv, .idp, .tokens et reports), avec vos migrations, code, tests, scripts, le fichier généré docs/test-report.md et REPORT.md :
# Larkfield document assistant: sign-in and two organizations## The model (people, organizations, memberships, roles; the access matrix on paper)## Identity (the provider copy, the clients, the audience, each token check, /v1/me)## Server rules (the check order, 404 or 403, the repository, row-level security or why not, files, search, citations, cache keys, the job, the audit)## Negative tests (the matrix, the object-level cases, the data rules, the attempts, the report, the three constructed bugs and what caught each one)## Lifecycle design (lifetimes, prevent or bound for each place, the measured removal, key rotation)## Real provider (the mapping, the evidence level, what a first real run must check)## Failure paths (each of the ten, with the test or the run that shows it)## Fresh-environment run (the commands and their outputs)## Limits (made-up data, your computer, what you copied, what you did not test)Comment le travail est évalué
Section intitulée « Comment le travail est évalué »Un réviseur note chaque élément requis démontré, partiellement démontré ou pas encore démontré, avec une raison concrète. Pour terminer le cours, vous devez démontrer les quatre éléments. Vous pouvez améliorer un élément et le soumettre de nouveau.
| Élément requis | Démontré | Partiellement démontré, par exemple | Pas encore démontré, par exemple |
|---|---|---|---|
| Contexte d’identité validé | Chaque route vérifie la signature, l’émetteur, l’audience, l’expiration et l’algorithme. Les tests nomment la vérification pour chaque jeton invalide. Un jeton ticket-api et un jeton d’identité reçoivent le code 401. /v1/me lit les adhésions dans la table du service lui-même. |
Les vérifications fonctionnent, mais le service récupère les clés à chaque requête. Ou il vérifie le type de jeton, mais pas l’audience. | L’audience est encore ticket-api, donc un jeton de l’autre service fonctionne. Ou l’organisation ou le rôle provient d’une revendication (claim) du jeton ou d’un en-tête. |
| Règles de rôle et de ressource appliquées par le serveur | Chaque route qui traite les enregistrements d’une organisation exécute les vérifications dans l’ordre. Chaque fonction du dépôt exige l’organisation. Les fichiers, la recherche, les citations, les clés de cache et la tâche portent l’organisation et le niveau d’accès. Chaque refus laisse un événement d’audit sans jeton. | Les routes sont correctes, mais une instruction ou une clé de cache n’a pas d’organisation. Seule la sécurité au niveau des lignes évite alors une fuite. Ou le service vérifie la tâche à sa mise en file d’attente, mais pas à son exécution. | Un membre en lecture seule peut téléverser un document ou voir un document réservé au personnel dans une citation. Ou le service signe un lien de fichier avant la vérification. |
| Tests négatifs entre organisations | La matrice couvre chaque personne, organisation et route, ainsi que les identités invalides et les cas d’accès aux objets. Un test des règles compare decide() au document. Le rapport est généré et compte les vérifications ignorées comme non réussies. Toutes les vérifications réussissent. Les tests détectent chacun des trois bogues construits, et le rapport indique lesquels les détectent. |
La matrice couvre les rôles, mais pas les vrais identifiants de l’autre boutique. Ou le rapport est rédigé à la main. | Les tests couvrent seulement les cas où tout fonctionne. Ou une vérification entre organisations échoue. |
| Conception du cycle de vie des jetons et des sessions | Chaque durée de vie a une valeur et une raison. Chaque endroit où une autorisation persiste est éliminé ou limité dans le temps, et le retrait est mesuré. La rotation des clés suit le bon ordre. Les paramètres du vrai fournisseur sont associés à la conception, avec un niveau de preuve honnête. | Les durées de vie sont indiquées, mais les réponses en cache ou les tâches en file d’attente sont oubliées. Ou Entra ID est décrit comme « fonctionnel » sans exécution. | Aucune conception pour le retrait ou l’expiration. Ou la conception permet à un membre retiré de garder l’accès jusqu’à l’expiration du jeton, sans mesure ni justification. |
Quelles que soient les autres forces du travail, il reste incomplet si une vérification entre organisations ou d’élévation de privilèges échoue. Un cas où tout fonctionne ne compte pas si une personne peut lire, modifier ou citer un enregistrement d’une autre organisation. Il ne compte pas non plus si un rôle dépasse les autorisations de sa ligne dans la matrice. Une fuite reste une fuite, même avec une belle interface.
Les résultats du cours peuvent vous aider à évaluer les vôtres, mais ce ne sont pas des cibles. Sur l’ordinateur du cours, la matrice de l’API de billets de soutien a réussi 213 vérifications sur 213. Les tentatives ont obtenu un résultat de 0 sur 10. Un membre retiré a reçu le code 404 à la requête suivante, 5 ms plus tard. Un cache d’adhésions de 30 secondes a permis à un membre retiré de continuer à lire pendant 30,3 secondes. Votre service, ses routes et votre ordinateur sont différents.
Erreur courante
Votre service accepte les jetons de l'API de billets
Symptôme : un jeton obtenu avec python -m scripts.login --user usr-sam --print-access-token dans ticket-api reçoit le code 200 de votre service. Ou votre jeton reçoit le code 200 de ticket-api.
Cause : la vérification d’audience attend encore ticket-api, la valeur par défaut du fichier auth.py copié. Ou votre copie du fournisseur écrit encore ticket-api dans aud (audience). Deux services qui font confiance aux mêmes clés et à la même audience acceptent les jetons l’un de l’autre.
Correction : définissez l’audience à docs-assistant dans la copie du fournisseur et dans les paramètres du service. Exécutez le fournisseur sur son propre port, avec son propre émetteur. Ajoutez le jeton de l’API de billets à vos identités invalides. Ainsi, la matrice détectera le problème s’il revient.
Récapitulatif
Dans ce cours, vous avez rendu une API sûre pour plusieurs organisations :
- Trois questions distinctes : qui appelle (un jeton ou une session vérifiés), dans quelle organisation (le chemin et l’adhésion de l’appelant), et avec quelles autorisations (le rôle et les portées du jeton).
- Jetons et sessions : OIDC avec PKCE, jetons signés vérifiés sur le serveur, session côté serveur avec témoin (cookie) HttpOnly, et durées de vie justifiées.
- Règles sur le serveur : 404 pour les personnes externes, 403 pour les membres. L’organisation figure dans chaque requête, lien de fichier, recherche, citation, clé de cache et tâche. La sécurité au niveau des lignes sert de deuxième verrou.
- Changements au fil du temps : retraits et changements de rôle qui prennent effet à la requête suivante. Vérification des tâches à leur exécution, accès de soutien justifié et limité dans le temps, et audit de chaque refus.
- Preuves : une matrice de tests qui essaie chaque personne sur chaque route, un rapport généré et une remise du travail. Celle-ci indique ce qui a été testé et ce qui reste ouvert.
Si vous n’en avez pas encore fait, choisissez une étude de cas pour le certificat : Auditer le contrôle d’accès d’une application multilocataire libre ou Ajouter la connexion et les rôles à une API existante.