This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
paul-synchro/doc.md

94 KiB
Raw Permalink Blame History

Brouillon de notes Recherche documentaire sur les différents concepts en jeu pour l'approvisionnement et la synchronisation des référentiels (dans le cadre de l'authentification et de la gestion des identités)

Stage P.Marillonnet

Compilation :

`markdown doc.md > doc.html

TODOs

  • Rédiger au propre les parties suffisamment documentées.
  • Scripts création markdown temporaire avec encodage html correct ?? (accents et caractères spéciaux)
  • Pour chaque projet libre, présenter un court historique de la naissance du projet (quels besoins ? quels instigateurs ? quelle licence ? quelle année ? quel(s) prédecesseur(s) ?)
  • Etudier préface du 'lasso book': concepts intéressants à expliquer + pdf lasso
  • Placer au fur et a mesure le contenu dans le rapport (draft_report\d*.md)

Avant de commencer

Acronymes

Annuaires

//BOOKMARK

SupAnn

PABX ?

NIS ?

DNS/Whois ? (pas vraiment de la GI ?)

Mécanismes d'authentification et implémentations

SASL (RFC2222)

TODO Paul

OpenID Connect

Utilisé pour la plateforme FranceConnect Plus facile à mettre en place que des solutions basées SAML ?

Identity Management

Principes généraux

Approvisionnement

Implémentations

SSO (et SLO)

Synchronisation

Fédération d'identités

Présentation

Concept très propre à la France Contraintes imposées par la Loi Informatique et Libertés (cf CNIL) techno-agnostic côté SP transparence pour l'utilisateur utilisation de la page de login de l'organisme de l'utilisateur pour l'identification et l'authentification sur le site ayant mis en place la fédération d'identités

Interdiction d'un croisement implicite des données, sans en avertir l'utilisateur

Plus grande probabilité de véracité des informations utilisateur Ces infos proviennent de sources sûres et à jour

TODO un SVG à faire ici, expliquant les mécanismes de la FI

TODO Relever les cas d'utilisation dans l'administration, les collectivités, et le monde de l'enseignement supérieur

Standards

Shibboleth

Appli Java Dépendances : Sprint OpenSAML Licence Apache

Contrôle d'accès

XACML

//TODIG

ALFA

//TODIG

Formulaires

POC

Presentation

Dans le cadre du projet Campus Condorcet, les annuaires de différents établissements doivent être regroupés en un méta-annuaire central. Aussi des problématiques d'homogénéisation de données hétérogènes se pose.

La phase de travail préparatoire à la réalisation du projet a consisté en le développement d'un POC (Proof Of Concept) permettant d'illustrer la procédure de constitution du méta-annuaire.

Le POC implémente un mécanisme simple d'ajout d'un compte invité ayant recours à un fournisseur de service, qui lui même repose sur un fournisseur d'identité SAML2 configuré pour assurer le SSO (Single Sign-On).

Déroulement de l'ajout du compte invité dans l'application POC

Suivant un scenario classique de SSO, l'authentification depuis le fournisseur de service (SP) est déléguée à un fournisseur d'identité (IdP). Le fournisseur d'identité conclut la phase d'authentification par le renvoi d'une assertion SAML validant l'authentification.

De nombreuses informations présentes dans l'assertion SAML seront ensuites réutilisées par le fournisseur de service. Le contenu complet de l'assertion SAML est consultable en annexes de ce document, à titre indicatif. On remarquera la normalisation de la majorité des entrées (noeuds, attributs, corps) XML des messages SAML.

En particulier, les champs SAML permettant d'identifier l'utilisateur connecté sont récupérés de l'assertion. Ces champs permettent de déterminer si l'utilisateur n'est pas déjà renseigné dans le méta-annuaire OpenLDAP (annuaire d'aggrégation des référentiels d'identités des établissements partenaires du projet).

Si l'utilisateur ne se trouve pas dans le méta-annuaire, la procédure d'ajout du compte doit être effectuée. Un formulaire est alors proposé à l'utilisateur, il lui permet de valider ses données d'identités et de choisir une unité d'affectation.

La création et la gestion du formulaire sont prises en charge par l'outil w.c.s. Cet outil se base sur la notion de workflow, c'est-à-dire la cohabitation de procédures automatisées de traitement de l'information d'un part, et le recours à des actions manuelles de la part d'agents d'autre part.

Une fois le formulaire rempli par l'utilisateur, le workflow est configuré pour l'envoi automatique d'un email à un agent, pour la confirmation de création du compte.

Le plugin Passerelle permet la communication avec l'annuaire, permettant l'ajout de l'entrée LDAP correspondant au compte nouvellement créé.

L'appel au plugin Passerelle doit être effectué en tant que phase du workflow. La validation de la demande doit être rendue possible par la génération d'un lien envoyé par email à l'agent.

TODO modification du contenu du message, pour ajouter la possibilité d'envoyer les données directement dans l'annuaire. FIXME quelle marge de manoeuvre sur la modification et l'ajout de données utilisateurs par l'agent ?

L'agent reçoit un email dont le contenu est :

Bonjour,

Un nouveau formulaire a =C3=A9t=C3=A9 compl=C3=A9t=C3=A9, vous pouvez le co=
nsulter
en suivant ce lien :
  http://wcs.example.com/backoffice/management/traitement/16/


Pour r=C3=A9f=C3=A9rence, voici le d=C3=A9tail du formulaire :

Email=C2=A0:
  toto@nowhere.null

Prenom=C2=A0:
  toto

Nom=C2=A0:
  t

NameID=C2=A0:
  tt

Unite d'affectation=C2=A0:
  hello

Par ailleurs, l'ajout d'un connecteur LDAP dans le plugin Passerelle permet de valider le formulaire et decréer l'entrée LDAP correspondante, par une requête GET sur l'URL: http:///wcs/

La modification de l'email généré se fait à l'aide de la classe EmailsDirectory défini dans le code source de w.c.s. (cf wcs.git/wcs/forms.py)

Cette classe est chargée d'enregistrer des templates d'email envoyés en fonction de la configuration du workflow associé au formulaire.

Nous retrouvons le template de l'email ci-dessus dans le fichier formdefs, à la ligne 1276. Le template est complété à l'aide de variables passées en paramètres. Elles sont pour l'instant au nombre de trois: name, url, details.

TODO Nous étudions maintenant la possibilité d'ajouter une quatrième variable correspondant à l'URL de validation exposée par l'API Passerelle.

./backoffice/management.py:33:from qommon.admin.emails import EmailsDirectory
./backoffice/management.py:72:        mail_subject = EmailsDirectory.get_subject('tracking-code-reminder')
./backoffice/management.py:73:        mail_body = EmailsDirectory.get_body('tracking-code-reminder')

Cf qommon/emails.py qommon/admin/emails.py

L'envoi de l'email est effectué dans wcs.git/wcs/workflows.py

Une option rapide a mettre en place: rajouter dans le formulaire l'URL de validation de celui-ci (validation au sens de Passerelle, une URL localhost:8007/wcs/

Problème non réentrance des vues du SP si inférence du numéro d'identifiant de la réponse au formulaire. Cette donnée ne devrait pas être manipulée avant création de l'entrée par WCS. C'est un ID autoincrémenté, mais cela pose quand même problème.

./lib/python2.7/site-packages/quixote/publish.py:291:def get_publisher():

Localiser la fonction de génération et d'envoi de l'email

dans wcs/qommon/emails.py

L'email est modifiable dans l'onglet Paramètres de l'interface backoffice de w.c.s.

Bonjour,

Un nouveau formulaire a été complété, vous pouvez le consulter
en suivant ce lien :
  [form_url_backoffice]

  Si nécessaire, vous pouvez approuver la demande en cliquant sur le lien http://localhost:8007/ldap/test3/wcs/[form_number]/

  [if-any details]
  Pour référence, voici le détail du formulaire :

  [details]
  [end]

Pas de modif ?

Pistes d'identifications du bug:

  • regeneration des fichiers de traduction .po ? non
  • basculer GNOME en anglais pour forcer l'envoi du mail dans la locale adéquate ? non
  • installation de wcs à l'aide du paquet Debian ? non
  • modification en dur du template de l'email dans le code ? non
  • prise en compte de modifs avec l'utilitaire wcsctl.py ? non
  • rechargement de la config Apache ? non
  • mauvaise conf SMTP ? voir exim4-light ? peu probable ... TODO
  • template de l'email persistant, dans la base ? à voir, la commande wcsctl.py shell ne fonctionne pas pour l'instant TODO
  • inspection pdb ? à voir TODO
  • externalisation des templates d'email dans un repertoire extérieur au projet ? TODO
  • exploration de la base, des migrations, pour comprendre la façon dont sont stockées les objets de template d'emails

Debugger : le template de l'email semble avoir été enrgistré:

(Pdb) EmailsDirectory.emails_dict
{'new_user': {'category': 'Workflow', 'default_body': 'Hello,\n\n[if-any user]\nThis mail is a reminder about the form you just submitted; you can consult it\nwith this link: [url]\n[else]\nThis mail is a reminder about the form you just submitted.\n[end]\n\n[if-any details]\nFor reference, here are the details:\n\n[details]\n[end]\n', 'description': 'Notification of creation to user', 'hint': None, 'enabled': False, 'default_subject': 'New form ([name])'}, 'change_user': {'category': 'Workflow', 'default_body': 'Hello,\n\n[if-any form_status_changed]\nStatus of the form you submitted just changed (from "[before]" to "[after]").\n[end]\n\n[if-any user]\nYou can consult it with this link:\n[url]\n[end]\n\n[if-any form_comment]New comment: [form_comment][end]\n\n[if-any evolution]\n[evolution]\n[end]\n', 'description': 'Notification of change to user', 'hint': 'Available variables: user, url, before, after, evolution', 'enabled': False, 'default_subject': 'Form status change'}, 'new_receiver': {'category': 'Workflow', 'default_body': 'Hello,\n\nA new form has been submitted, you can see it with this link:\n[form_url_backoffice]\n\nIf necessary, please validate the submission by visiting:\nhttp://localhost:8007/ldap/test3/wcs/[form_number]/\n\n[if-any details]\nFor reference, here are the details:\n\n[details]\n[end]\n', 'description': 'Notification of creation to receiver', 'hint': 'Available variables: name, url, details', 'enabled': False, 'default_subject': 'New form ([name])'}}
(Pdb)

Pas d'anomalie detectee au debugger Python pour l'instant

Stack trace:

(Pdb) w
  /home/paul/devel/wcs/wcsctl.py(8)<module>()
  -> ctl.run(sys.argv[1:])
    /home/paul/devel/wcs/wcs/qommon/ctl.py(159)run()
    -> return cmd.run(args, options)
      /home/paul/devel/wcs/wcs/qommon/ctl.py(69)run()
      -> return self.execute(base_options, sub_options, args)
        /home/paul/devel/wcs/wcs/ctl/start.py(69)execute()
        -> import publisher
          /home/paul/devel/wcs/wcs/publisher.py(39)<module>()
          -> from root import RootDirectory
            /home/paul/devel/wcs/wcs/root.py(37)<module>()
            -> import forms.root
              /home/paul/devel/wcs/wcs/forms/root.py(49)<module>()
              -> from wcs.formdef import FormDef
              > /home/paul/devel/wcs/wcs/formdef.py(1299)<module>()
              -> EmailsDirectory.register('change_receiver', N_('Notification of change to receiver'),

Pas d'anomalie non plus sur la pile; c'est bien les sources qui sont executees et non le paquet Debian annexe

Il faudrait maintenant inspecter la trace de la fonction chargee d'envoyer l'email, pour vérifier la façon dont le template est récupéré. Comment mentionné précédemment, cette fonction est implementée dans le fichier wcs.git/wcs/common/emails.py

Pour l'instant, impossible de récuperer un shell dans ce fichier à l'aide de pdb.set_trace()

L'exécution de la commande python setup.py install ne résout pas non plus le problème.

Finalement, la modification du template est rendue possible par les icônes cliquables dans la section "Fabrique de workflow". L'action à paramétrer ici est "Juste envoyé" -> "Envoyer un courriel à Destinataire" Nous paramétrons l'email envoyé pour qu'il soit de la forme:

Bonjour,

Un nouveau formulaire a été complété, vous pouvez le consulter
en suivant ce lien :
  [form_url_backoffice]


Si necessaire, veuillez valider la demande en visitant le lien :
http://localhost:8007/ldap/test3/wcs/[form_number]/

[if-any details]
Pour référence, voici le détail du formulaire :

[details]
[end]

//TODO template pas très pro L'idéal serait de définir une variable validation_url, pour ne pas avoir à exposer l'URL de l'API de Passerelle directement dans le template de l'email. Nous pouvons maintenant nous pencher sur le scénario du cas d'utilisation décrit dans le diagramme de séquence.

L'agent doit pouvoir compléter les données relatives à l'utilisateur, ce qui signifique que le formulaire doit contenir des champs non remplissables par un utilisateur non authentifié. TODO Est-il alors nécessaire de comprendre comment est effectuée la gestion des droits dans wcs ?

Reduction du workflow à deux états, c'est suffisant pour ce que nous souhaitons faire.

Ajout de champs 'Bureau CC' et 'Téléphone CC' : infos inconnues de l'utilisateur inscrivant son compte invité.

Scenario d'utilisation relativement complet pas rapport au diagramme de séquence : passage à l'intégration Gadjo ?

TODO LIST pour l'instant

  • Message d'explication et inclusion charte graphique pour le HTTP 403 associé au décorateur @user_not_in_ldap
  • Gadjo dans w.c.s
  • Paramétrage d'un client mail pour la récupération automatique des emails dans ~/Maildir ?
  • Serveur SMTP envoyant des mails à une adresse effective, pas simplement dans ~/Maildir ?
  • Traitement du champ EduPersonPrincipalName (EPPN) tel que défini intialement dans le schéma ?
  • Compte-rendu POC avec captures d'ecran ?

2 bug collectstatic pas fonctionnel dans gadjo Definition de STATIC_ROOT dans le fichier settings.py ?

Note de mise en place du POC

### Préparation déploiement: 7 briques majeures:

  • SP
  • IDP
  • Gestion formulaires (WCS)
  • Base de connecteurs (Passerelle)
  • Serveur http (Apache)
  • Annuaire OpenLDAP (slapd)
  • serveur de mail (exim4)

Problème à gérer : pour l'instant pas de virtualenv commun aux 4 applications basées Django

SP

Importer le sous directory seulement ? Tout le virtualenv ? OUI Pas de config https vers authentic, est-ce un problème ? Homogénéisation des urls ?

Déploiement avec changement de l'URL

Pb: pas de fichier setup.py par défaut, il va falloir le créer

IDP

Créer un fichier de peuplement ? Export des données en local ?

Pb: mauvaise connaissence du format d'archive 'egg' pour les modules pythons L'utilitaire authentic2-ctl semble vouloir accéder à un dossier suffixé par l'extension 'egg', laquelle symbolise une format de compression... TODO troubleshooting...

System check identified no issues (0 silenced).
Unhandled exception in thread started by <function wrapper at 0x7f038144d848>
Traceback (most recent call last):
File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 229, in wrapper
fn(*args, **kwargs)
File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 116, in inner_run
self.check_migrations()
File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 168, in check_migrations
executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS])
File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 19, in __init__
self.loader = MigrationLoader(self.connection)
File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/db/migrations/loader.py", line 47, in __init__
self.build_graph()
File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/db/migrations/loader.py", line 185, in build_graph
self.load_disk()
File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/db/migrations/loader.py", line 93, in load_disk
for name in os.listdir(directory):
OSError: [Errno 20] Not a directory: '/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django_mellon-1.2.29-py2.7.egg/mellon/migrations'

Bugfix : suppression du fichier egg, réinstallation de django-mellon à l'aide du pip dans le virtualenv

Issue : plusieurs instances de projets différents déployés sur un même host TODO Recherche sur la config WSGI dans Apache2

Lecture de la doc dans le dossier Debian des sources Authentic -> Pas concluant

Essayer nginx et gunicorn ? option --config de authentic2-ctl

Problème de timeout sur gunicorn

Troubleshoot: Causes possibles:

  • Appli Django ? Peu problable : fonctionne en local...
  • socket Gunicorn <-> nginx ? La conf a l'air relativement simple
  • mauvaise configuration du serveur nginx ? Le timeout provient du worker gunicorn
  • structuration des sources authentic différente d'un projet django standard :
    • les applications sont situés dans src, et non pas directement à la racine du projet django
    • il n'y a pas de fichier manage.py, mais un script shebang authentic2-ctl
  • la configuration authentic pour gunicorn présume que authentic
  • problème avec le virtualenv ? pourtant le fichier gunicorn.sh laisse pense que la mise en place d'un environnement virtuel est prise en compte par gunicorn ,
  • problème de génération et de collecte des fichiers statiques ?
  • le module de gestion des scss est-il installée ?
  • incompatibilité lors du transfert du virtlanev local vers la dev ?

Identification des causes:

  • Fichier de log gunicorn ? Log en mode debug et pourtant rien de pertinent n'apparait...
  • Fichiers de log nginx : laisse à penser que la confi nginx est correct: rien de suspect...

Update :

2017/03/08 16:37:12 [error] 14502#0: *19 upstream prematurely closed connection while reading response header from upstream, client: 192.168.44.1, server: condorcet.dev.entrouvert.org, request: "GET / HTTP/1.0", upstream: "fastcgi://127.0.0.1:8000", host: "condorcet.dev.entrouvert.org"

-> L'erreur semble bel et bien provenir de gunicorn, la connexion est stoppée. Revenir a une config Apache et libabache2_mod_wsgi ? l'erreur se posera aussi, non ? Apache2 est-il plus souple en terme de front pour une application Django de structure non usuelle (pas de fichier manage.py ?)

Le plus logique serait de lire la documentation gunicorn pour comprendre ce qui ne va pas Il faut aussi comprendre laquelle des deux installations de gunicorn est la plus adaptée :

  • avec pip dans le virtualenv ?
  • avec apt-get dans l'environnement glogal du conteneur ?

Y a-t-il des différences dans la gestion des fichiers statiques par Apache et nginx ? Comprendre l'interface Django <-> Apache par WSGI peut-être plus simple à comprendre pour une seule appli, par rapport à nginx ?

Avec Apache2 et mod_wsgi : 403 forbidden:

  • possibles ? pas de certificats ?

TODO : reactiver le mode de debugging ?

Problème de cohabitation Apache et nginx

Les VirtualHost Apache seuls ne semblent pas adaptables ?

Comment faire dans le cas où les projets sont installés à partir des paquets Debian ?

Déploiement manuel et configuration des VirtualHost pas évidente...

Les deux serveurs écoutent chacun sur des ports TCP différents :

Proto Recv-Q Send-Q Adresse locale          Adresse distante        Etat        PID/Program name
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      2973/nginx -g daemo
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1545/apache2

Apache WCS OK :

wget condorcet.dev.entrouvert.org
--2017-03-10 15:17:14--  http://condorcet.dev.entrouvert.org/
Resolving condorcet.dev.entrouvert.org (condorcet.dev.entrouvert.org)... 188.165.196.219
Connecting to condorcet.dev.entrouvert.org (condorcet.dev.entrouvert.org)|188.165.196.219|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 561 [text/html]
Saving to: index.html

index.html                                            100%[======================================================================================================================>]     561  --.-KB/s    in 0s

2017-03-10 15:17:14 (101 MB/s) - index.html saved [561/561]

nginx Authentix nettement moins OK :

wget condorcet.dev.entrouvert.org:8080
--2017-03-10 15:17:18--  http://condorcet.dev.entrouvert.org:8080/
Resolving condorcet.dev.entrouvert.org (condorcet.dev.entrouvert.org)... 188.165.196.219
Connecting to condorcet.dev.entrouvert.org (condorcet.dev.entrouvert.org)|188.165.196.219|:8080...

On essaie alors en local, sur la dev, de générer des logs :

root@condorcet:~# wget localhost:8080
--2017-03-10 15:24:11--  http://localhost:8080/
Résolution de localhost (localhost)… ::1, 127.0.0.1
Connexion à localhost (localhost)|::1|:8080… échec : Connexion refusée.
Connexion à localhost (localhost)|127.0.0.1|:8080… connecté.
requête HTTP transmise, en attente de la réponse… Aucune donnée reçue.
Nouvel essai.

--2017-03-10 15:24:12--  (essai :  2)  http://localhost:8080/
Connexion à localhost (localhost)|127.0.0.1|:8080… connecté.
requête HTTP transmise, en attente de la réponse… Aucune donnée reçue.
Nouvel essai.

--2017-03-10 15:24:14--  (essai :  3)  http://localhost:8080/
Connexion à localhost (localhost)|127.0.0.1|:8080… connecté.
requête HTTP transmise, en attente de la réponse… Aucune donnée reçue.
Nouvel essai.

--2017-03-10 15:24:17--  (essai :  4)  http://localhost:8080/
Connexion à localhost (localhost)|127.0.0.1|:8080… connecté.
requête HTTP transmise, en attente de la réponse… Aucune donnée reçue.
Nouvel essai.

--2017-03-10 15:24:21--  (essai :  5)  http://localhost:8080/
Connexion à localhost (localhost)|127.0.0.1|:8080… connecté.
requête HTTP transmise, en attente de la réponse… Aucune donnée reçue.
Nouvel essai.

Le serveur renvoie des HTTP 444 :

root@condorcet:/etc/nginx# cat /var/log/nginx/access.log
127.0.0.1 - - [10/Mar/2017:15:24:11 +0100] "GET / HTTP/1.1" 444 0 "-" "Wget/1.16 (linux-gnu)"
127.0.0.1 - - [10/Mar/2017:15:24:12 +0100] "GET / HTTP/1.1" 444 0 "-" "Wget/1.16 (linux-gnu)"
127.0.0.1 - - [10/Mar/2017:15:24:14 +0100] "GET / HTTP/1.1" 444 0 "-" "Wget/1.16 (linux-gnu)"
127.0.0.1 - - [10/Mar/2017:15:24:17 +0100] "GET / HTTP/1.1" 444 0 "-" "Wget/1.16 (linux-gnu)"
127.0.0.1 - - [10/Mar/2017:15:24:21 +0100] "GET / HTTP/1.1" 444 0 "-" "Wget/1.16 (linux-gnu)"

Ce qui correspond à la conf de /etc/nginx/conf.d/return-444-if-no-host-header.conf

Pas de host header wsgi cassé ?

root@condorcet:~# find / -name authentic2
/var/log/authentic2
/var/lib/authentic2
/var/lib/authentic2/collectstatic/authentic2
/var/cache/authentic2
/etc/cron.d/authentic2
/etc/logrotate.d/authentic2
/etc/nginx/sites-enabled/authentic2
/etc/nginx/sites-available/authentic2
/etc/authentic2
/etc/init.d/authentic2
/etc/cron.hourly/authentic2
/usr/share/authentic2
/usr/share/doc/authentic2
/usr/share/dbconfig-common/scripts/authentic2
/usr/lib/authentic2
/usr/lib/python2.7/dist-packages/authentic2
/usr/lib/python2.7/dist-packages/authentic2/manager/templates/authentic2
/usr/lib/python2.7/dist-packages/authentic2/manager/static/authentic2
/usr/lib/python2.7/dist-packages/authentic2/templates/authentic2
/usr/lib/python2.7/dist-packages/authentic2/static/authentic2
/usr/lib/python2.7/dist-packages/hobo/agent/authentic2
/run/authentic2

Authentic écoute bien en local sur le port 8000 tcp 0 0 127.0.0.1:8000 0.0.0.0:* LISTEN 7654/python

 ps -aux | grep 7654
 root      4239  0.0  0.0  12628  1076 pts/4    R+   15:48   0:00 grep 7654
 authent+  7654  1.5  2.7 253900 56740 pts/2    Sl   mars09  21:41 /usr/bin/python /usr/lib/authentic2/manage.py runserver

Le code de retour 444 ne semble pas symboliser une erreur côté serveur mais plutôt une incohérence dans la requête du client (champ Host de la requête HTTP laissé vide ?) Pourtant le champ HOST est bien rempli dans a requête GET: Host: "condorcet.dev.entrouvert.org:8080"

root@condorcet:~# wget condorcet.dev.entrouvert.org:8080
--2017-03-10 16:10:44--  http://condorcet.dev.entrouvert.org:8080/
Résolution de condorcet.dev.entrouvert.org (condorcet.dev.entrouvert.org)… 192.168.43.32
Connexion à condorcet.dev.entrouvert.org (condorcet.dev.entrouvert.org)|192.168.43.32|:8080… connecté.
requête HTTP transmise, en attente de la réponse… 502 Bad Gateway
2017-03-10 16:10:44 erreur 502 : Bad Gateway.
2017/03/10 16:10:44 [error] 4569#0: *2 upstream sent unsupported FastCGI protocol version: 60 while reading response header from upstream, client: 192.168.43.32, server: condorcet.dev.entrouvert.org, request: "GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:8000", host: "condorcet.dev.entrouvert.org:8080"

Après simplification de la conf:

># wget condorcet.dev.entrouvert.org:8080
--2017-03-10 16:15:53--  http://condorcet.dev.entrouvert.org:8080/
Résolution de condorcet.dev.entrouvert.org (condorcet.dev.entrouvert.org)… 192.168.43.32
Connexion à condorcet.dev.entrouvert.org (condorcet.dev.entrouvert.org)|192.168.43.32|:8080… connecté.
requête HTTP transmise, en attente de la réponse… 200 OK
Taille : non indiqué [text/html]
Sauvegarde en : « index.html »

index.html                                                [ <=>                                                                                                                     ]   1,89K  --.-KB/s   ds 0s    

2017-03-10 16:15:54 (166 MB/s) - « index.html » sauvegardé [1939]

Prochaine étape: Distant D'abord depuis mesclun ?

FIX : utilisation de sous domaines séparateur '.' ne fonctionne pas, en revanche '-' fonctionne (pydns)

utilisation de dig :

# dig condorcet.dev.entrouvert.org

; <<>> DiG 9.9.5-9+deb8u10-Debian <<>> condorcet.dev.entrouvert.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12770
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;condorcet.dev.entrouvert.org.  IN  A

;; ANSWER SECTION:
condorcet.dev.entrouvert.org. 60 IN A   188.165.196.219

;; AUTHORITY SECTION:
dev.entrouvert.org. 228 IN  NS  ns.dev.entrouvert.org.

;; ADDITIONAL SECTION:
ns.dev.entrouvert.org.  228 IN  A   188.165.196.219

;; Query time: 6 msec
;; SERVER: 5.135.221.23#53(5.135.221.23)
;; WHEN: Fri Mar 10 16:40:26 CET 2017
;; MSG SIZE  rcvd: 106

root@condorcet:/var/log/nginx# dig connexion-condorcet.dev.entrouvert.org

; <<>> DiG 9.9.5-9+deb8u10-Debian <<>> connexion-condorcet.dev.entrouvert.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12958
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;connexion-condorcet.dev.entrouvert.org.    IN A

;; ANSWER SECTION:
connexion-condorcet.dev.entrouvert.org. 60 IN A 188.165.196.219

;; AUTHORITY SECTION:
dev.entrouvert.org. 204 IN  NS  ns.dev.entrouvert.org.

;; ADDITIONAL SECTION:
ns.dev.entrouvert.org.  204 IN  A   188.165.196.219

;; Query time: 8 msec
;; SERVER: 5.135.221.23#53(5.135.221.23)
;; WHEN: Fri Mar 10 16:40:50 CET 2017
;; MSG SIZE  rcvd: 116

ip addr add dev venet0 192.168.43.33/32

Modification de /etc/hosts pour la prise en compte des deux IP:

192.168.43.32 condorcet.dev.entrouvert.org  condorcet
192.168.43.33 idp-condorcet.dev.entrouvert.org  condorcet
::1     localhost ip6-localhost ip6-loopback

Avec netstat on a alors :

Connexions Internet actives (seulement serveurs)
Proto Recv-Q Send-Q Adresse locale          Adresse distante        Etat        PID/Program name
tcp        0      0 192.168.43.33:80        0.0.0.0:*               LISTEN      6232/nginx -g daemo
tcp        0      0 192.168.43.32:80        0.0.0.0:*               LISTEN      6075/apache2   

TODO Puppet et repo git pour la conf ?

BLOCKER: installation authentic2 a partir du paquet debian non fonctionnelle, pas de logs -> Désinstallation WORKAROUND: faire tourner authentic à partir des sources, avec ./authentic2-ctk runfcgi

Pb de configuration ? Revenir une énième fois à gunicorn ?

$ ./authentic2-ctl runfcgi method=threaded host=127.0.0.1 port=8080 Creation d'un thread

TODO quelles différences avec le mode prefork ?

Unhandled exception -> Quels logs ?

L'exception provient de flup:

2017/03/14 10:14:26 [error] 18062#0: *7 FastCGI sent in stderr: "Traceback (most recent call last):
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/flup/server/fcgi_base.py", line 558, in run
    protocolStatus, appStatus = self.server.handler(self)
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/flup/server/fcgi_base.py", line 1118, in handler
    result = self.application(environ, start_response)
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 189, in __call__
    response = self.get_response(request)
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 207, in get_response
    return debug.technical_500_response(request, *sys.exc_info(), status_code=400)
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/views/debug.py", line 97, in technical_500_response
    html = reporter.get_traceback_html()
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/views/debug.py", line 384, in get_traceback_html
    return t.render(c)
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/template/base.py", line 210, in render
    return self._render(context)
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/template/base.py", line 202, in _render
    return self.nodelist.render(context)
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/template/base.py", line 905, in render
    bit = self.render_node(node, context)
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/template/debug.py", line 79, in render_node
    return node.render(context)
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/template/defaulttags.py", line 329, in render
    return nodelist.render(context)
  File "/home/pmarillonnet/devel/venv/local/lib/python2.7/site-packages/django/template/base.py", line 905, 

=> Retour à gunicorn, voir si ça change quoi que ce soit Ok gunicorn il faut vieiller à réinstaller le package (/usr/lib/python2.7/dist-packages) Installation Authentic fonctionnelle

WCS

Un simple export global devrait suffire Pb : WCS configuré avec Apache pour l'instant Ici seul nginx est utilisé ! Mais WCS necessaire en local seulement ? Oui, c'est passerelle qui doit être accessible depuis l'extérieur WCS en backend seulement

pb: upload de la conf avec lynx Ecouter sur le port 80 juste pour l'upload de la conf ? Oui, une fois la config faite, on le rebascule, en local seulement, sur 8080

2 choix:

  • serveur http embarqué dans wcs ? -> Ce n'est pas la solution optimale
  • config scgi DONE

Timeout sur l'interrogation de l'annuaire TODO Dummy git repo C'est le décorateur qui timeout

#### Passerelle Export du connecteur créé

Plus complexe que le l'IdP et le gestionnaire de formulaire Cette fois-ci une installation à partir du paquet Debian paraît difficilement réalisable, pour la raison que les sources doivent être patchées afin de pouvoir incorporer le connecteur LDAP. Mais le projet présente l'avantage d'un structuration plus 'canonique', ce qui facilite la recherche de documentation générique sur le déploiement des projets Django et de la conf WSGI.

On essaie alors de configurer un nouveau VirtualHost Apache avec l'une des adresse privées attribuées à l'interface virtuelle du conteneur

$ ip a s                                                                                                  │
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN                                       │
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00                                                 │
    inet 127.0.0.1/8 scope host lo                                                                        │
    inet6 ::1/128 scope host                                                                              │
       valid_lft forever preferred_lft forever                                                            │
2: venet0: <BROADCAST,POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN                 │
    link/void                                                                                             │
    inet 127.0.0.2/32 scope host venet0                                                                   │
    inet 192.168.43.32/32 brd 192.168.43.32 scope global venet0:0                                         │
    inet 192.168.43.33/32 scope global venet0                                                             │
    inet 192.168.43.34/32 scope global venet0                                                             │
    inet 192.168.43.35/32 scope global venet0                                                             │

Première étape : runserver local sur le port 8080 2e étape : Apache + mod_wsgi 3e etape (post déploiement) : réécriture plus propre du connecteur, en exploitant les fonctionnalités endpoints de Passerelle

  1. Ok sans virtualenv (c'est ce qui est plus approprié pour une machine en dev)
  2. Utilisation du mode daemon de wsgi pour l'exécution en parallèle de plusieurs backends Django sur un seul environnement python.

UPDATE: pas besoin d'exposer l'interface Web de Passerelle utilisation backend seulement. Conf ok, juste les URLs codées 'en dur' dans les sources, à modifier

BLOCKER: Connecteur LDAP plus reconnu par l'appli Pourtant les migrations ont été appliquées

FIX?: suppression des restes de l'installation globale passerelle (/usr/lib/python2.7/dis-packages/passerelle) avec apt-get remove --purge passerelle python-passerelle Non, toujours cette même erreur Les sources ne sont-elles pas installées ailleurs ?

Pb de conflit avec le virtualenv initial Reinstallation de l'appli

FIX: ne pas redefinir get_add_url dans le modèle du connecteur hérité de BaseResource, les underscores sont transformés en dashes... c'est ldap-dir qui apparait dans les URLs, et non pas ldap_dir

Serveur HTTP

Config SSL/TLS pas utilisée Revoir la config wcs, ie la façon dont l'application est repartie entre source, app_dir et data_dir

Annuaire OpenLDAP

Retrouver le fichier de peuplement de l'annuaire ? Pas nécessaire, juste besoin de recréer les noeuds intermédiaires de l'arborescence.

Installation slapd TODO : retrouver les lignes de commande d'interrogation du LDAP Fichier usual_ldap_commands

ldaputils pour le test en local...

Prise en compte du rebond ssh pour le transfert de fichier ssh pour le lancement d'une commande sur la machine intermédiair

Creation d'un fichier de peuplement minimal quelques groupes et une entrée bidon

# ldapadd -x -D "cn=admin,dc=condorcet,dc=dev,dc=entrouvert,dc=org" -w test -p 389 -h `hostname -f` -f /home/pmarillonnet/Documents/
misc/Example_shrunk.ldif
adding new entry "dc=org"
ldap_add: Server is unwilling to perform (53)
        additional info: no global superior knowledge


Ajout OK, avec comme fichier ldif:

idn: ou=Servers,dc=condorcet,dc=dev,dc=entrouvert,dc=org
objectClass: organizationalUnit
objectClass: top
description: Company Servers
ou: Servers

dn: ou=Groups,dc=condorcet,dc=dev,dc=entrouvert,dc=org
objectClass: organizationalunit
objectClass: top
ou: Groups

dn: ou=Managers,ou=groups,dc=condorcet,dc=dev,dc=entrouvert,dc=org
objectClass: top
objectClass: organizationalunit
ou: groups
description: People who can manage accounting entries
ou: Managers

dn: ou=People,dc=condorcet,dc=dev,dc=entrouvert,dc=org
objectClass: organizationalunit
objectClass: top
ou: People

dn: uid=jmorrison,ou=People,dc=condorcet,dc=dev,dc=entrouvert,dc=org
objectClass: person
#objectClass: cos
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: posixAccount
objectClass: top
uid: jmorrison
#classOfService: gold
userpassword: chevron
facsimiletelephonenumber: +1 408 555 4661
givenname: Jim
cn: Jim Morrison
telephonenumber: +1 408 555 9445
sn: Morrison
roomnumber: 2290
homeDirectory: /home/jmorrison
mail: jmorrison@example.com
l: Pere Lachaise
ou: People
uidNumber: 1119
gidNumber: 1000

On suppose que le dn global a été créé lors de la (re)configuration dpkg

Exim4

dpkg reconfigure pour obtenir la config souhaitée faire une config pour l'envoi de mails vers une adresse réelle ? Dans /home//Maildir pour l'instant

Pb exim4 : les ports ne sont pas ouverts Deux solutions Workaround en passant tout de même par leucas ? Configuration d'un serveur SMTP en local ? Préférable ?

Les messages ICMP echo request vers l'extérieur ne passent même pas. Ok pb config réseau résolu par redémarrage de la VM Déploiement OK

Procédure de déploiement

  • Tarballs -> OK
  • Fonctionnement en local -> En cours

Améliorations envisagables

Gadjo sur le SP Gadjo sur la page finale passerelle Adaptation SupAnn 2009

Adaptation au schéma SupAnn 2009

classes de l'entrée:

  • organization (RFC2798)
  • dcObject (RFC2247)
  • eduOrg
  • supannOrg

avec les attributs:

  • o
  • supannEtablissement

Nous nous intéresserons ici à l'un des trois branches seulement de cette entrée : ou=People

Nous gérons les comptes invités en tant que personne, indépendamment de l'approvisionnement des groupes (ou=groups) et des structures (ou=structures)

Les entrées de la branche des personnes se base sur trois classes : inetOrgPerson en tant que classe structurelle et eduPerson et supannPerson en tant que classes auxiliaires.

L'import d'un compte invité dans le méta-annuaire doit tenir compte de l'établissement : l'attribut supannCodeEntite de la personne renvoie au supannCodeEntite de l'établissement et l'attribut supannEtablissement de la personne référence le code UAI.

On peut alors établir les différents champs qui seront présents dans le formulaire d'inscription du compte invité :

  • nom
  • prenom
  • adresse email
  • établissement
  • affiliation principale (facultatif)
  • affectation principale (facultatif)
  • corps d'appartenance
  • liste rouge

//TODO faut-il collecter aussi les infos concernant la personne invitante ?

Les attributs transmis lors du SSO vont servir au préremplissage du formulaire final. Attention, certains de ces attributs ne sont pas éditables. Au total, il y a en 11 :

  • eduPersonPrincipalName (non éditable)
  • surname
  • givenName
  • mail
  • supannEtablissemnt
  • eduPersonPrimaryAffiliation
  • eduPersonAffiliation
  • supannEntiteAffectationPrincipale
  • supannEntiteAffectation
  • supanEmpCorps
  • supannListeRouge

L'absence d'une information obligatoire stoppe la procédure de soumission du formulaire.

Il faut maintenant gérer la transmission des attributs depuis l'IdP source. Changements à répercuter : le SP avec tout le code django-mellon WCS lors de la définition des formulaires les utilitaires basés python-ldap3 lors de la création de la requête vers le meta-annuaire

Bien sur la transmission des attributs dans l'IdP, via l'assertion SAML envoyée, doit tenir compte de l'adoption du schéma SupAnn 2009.

TODO comprendre comment est mis en place l'annuaire supann du côté de l'IdP source => Lecture de la doc Authentic2 PSL http://doc.entrouvert.org/supann/

TODO : serveur LDAP avec inclusion du schéma SupAnn 2009 outil web de gestion des entrées LDAP -> LdapSaisie Un IdP SAML2

TODO quelles normes pour la fédération d'identités Renater ?

Ici méta-annuaire décrit comme l'utilisation de plusieurs branches au sein du même annuaire, synchronisées vers un annuaire distant.

Utilisation de NTP pour la synchro des horloges

LdapSaisie : de quel côté l'installer ? sur condorcet ou en local ? pb : appli apache php, pas de doc pour nginx

Essayer une installation PHP FPM ?

On passe cette étape pour l'instant : la configuration et la gestion de l'annuaire SUPANN2009 se fera en ligne de commande, comme pour le LDAP générique.

Ici utilisation d'une machine unique, même si en pratique il faudrait installer chaque composant sur des machines séparées... Façon plus propre de déployer une application multi-bloc

Le LDAP est déjà fonctionnel, alors comment inclure proprement le schéma supann ? Lecture de la doc : installation de authentic2-supann ?

Le repo git ne contient que des conf et un script La conf nginx est-elle différente de l'install authentic2 classique ? Modifier le settings.py de authentic pour la configuration du backend db ?

Comment faire remonter les attributs supann dans la politique de transmission SAML d'arguments, dans la GUI Web de authentic2 ? TODO adapter le config.py situé dans le dépôt ?

Pour l'instant le poc n'est pas en https, il fonctionne sans certificats. Faut-il les générer pour que fonctionne la configuration supann ?

Récupération du schéme SupAnn 2009 pour OpenLDAP sur le site RENATER. Ce n'est pas l'objectif principal pour l'instant : la mise en place du schéma côté annuaire semble plutôt légère, mais c'est le support IdP qui pour l'instant semble poser problème.

Y a-t-il forcément besoin d'un backend LDAP pour l'IdP du POC ? Cela pose problème : l'installation est locale seulement Faire un LDAP avec deux branches ? l'une pour l'annuaire local de l'IdP (côté invité) et l'autre pour le méta-annuaire (côté CC) ?

Ce qui est faisable pour l'instant : l'installation d'un OpenLDAP SupAnn pour le méta annuaire Ce qu'on pourrait faire par la suite :

  • Cohabitation de deux slapd sur des ports différents ? Préférable
  • Un seul slapd qui gère deux branches différentes : l'une côté client et l'autre côté CC ? Difficile et pas pertinent...

1ere étape : installation du schéma Cette install se fait par placement d'un fichier ldif dans les répertoires de configuration de slapd. Ok, génération d'un LDIF que l'on va passer à ldapadd

 # slaptest -f ldap_includes.conf -F ldif_output/
 58e24560 /etc/ldap/schema/collective.schema: line 28 attributeType: AttributeType not found: "l"
 slaptest: bad configuration directory!

Pb réglé après modification de l'ordre de déclaration des différents schémas. On peut alors, après modification de /cn=config/cn=schema/cn={8}misc.ldif telle que décrite dans http://www.linuxquestions.org/questions/linux-server-73/how-to-add-a-new-schema-to-openldap-2-4-11-a-700452/ procéder à un ldapadd du ldif généré

ldapadd -x -D "cn=admin,dc=condorcet,dc=dev,dc=entrouvert,dc=org" -w test -p 389 -h condorcet.dev.entrouvert.org -f /home/pmarillonnet/Documents/misc/ldif_output/cn\=config/cn\=schema/cn\=\{8\}misc.ldif

renvoie une erreur 50 (insufficient access) et pourtant

ldapsearch -D "cn=admin,dc=condorcet,dc=dev,dc=entrouvert,dc=org" -w test -p 389 -h condorcet.dev.entrouvert.org -b "ou=People,dc=condorcet,dc=dev,dc=entrouvert,dc=org" -s sub "(ObjectClass=*)" * +

s'exécute correctement.

La conf d'accès à l'administration de l'annuaire ne semble pas se trouver dans son emplacement par défaut

# grep -nr pw ./
# grep -nr root ./
#

On peut essayer d'utiliser slapadd en local au lieu de l'utilitaire client ldapadd ?

Résolution par ajout d'un mot de passe pour la configuration de l'annuaire

 # slappasswd -h {MD5}
 New password: 
 Re-enter new password: 

Ajout d'une ligne olcRootPW: {md5}... dans /etc/ldap/slapd.d/cn=config/olcDatabase={0}config.ldif résout le problème :

$ ldapadd -x -D "cn=admin,cn=config" -w test -p 389 -h condorcet.dev.entrouvert.org -f /home/pmarillonnet/Documents/misc/ldif_output/cn\=config/cn\=schema/cn\=\{8\}misc.ldif
adding new entry "cn=misc,cn=schema,cn=config"

Pas certain cependant que l'adaptation supann ait été effectuée :

$ ldapsearch -D "cn=admin,cn=config" -w test -p 389 -h condorcet.dev.entrouvert.org -b "cn=config" -s sub "(ObjectClass=*)" * + | grep -i  supann

ne renvoie rien

La commande ldapadd ci-dessus ne semble avoir ajouté qu'une seule entrée (misc)

Revenons au fichier LDIF, quelque chose doit manquer Une seule entrée en effet, l'opération slaptest s'est mal déroulée

Plantage dans la procédure : lire une documentation un peu plus spécifique à SupAnn : il ne s'agirait pas simplement d'ajouter un schéma.

On part vers quelque chose d'un peu plus détaillé, par exemple http://www.it-sudparis.eu/s2ia/user/procacci/ldap/Ldap_int018.html

TODO? eplucher le script perl NO: il s'agit simplement d'un script de migration d'un annuaire générique au format supann

Maintenant: adaptation de la doc trouvée sur linuxquestions le schema manipulé est supann_2009 on supprime le {\d*} comme indiqué dans la doc, ainsi que le dernier paragraphe

une erreur survient cependant encore: l'entrée que l'on souhaite ajoutée n'est rattaché nulle part dans l'arborescence de l'annuaire on change cn=supann_2009 pour cn=supann_2009,cn=schema,cn=config

L'entrée est ajoutée

TODO devient-il alors possible de lui rattacher des entrées de type supannPerson

Il faut tout d'abord définir une branche supannPeople ? Reprendre et adapter le example.ldif utilisé précédemment

Les spécifications issue du document d'analyse ('Analyse v0.4.odt') stipulent que les entrées de la branche doivent appartenir aux trois classes d'objets inetOrgPerson, eduPerson et supannPerson

TODO quelles implications de la distrinction entre classe structurelle et classes auxiliaires ?

erreur :

$ ldapadd -x -D "cn=admin,dc=condorcet,dc=dev,dc=entrouvert,dc=org" -w test -p 389 -h condorcet.dev.entrouvert.org -f ~/Documents/supann/Example_supann.ldif 
adding new entry "ou=supannPeople,dc=condorcet,dc=dev,dc=entrouvert,dc=org"
ldap_add: Already exists (68)

Ok, on a une erreur lors de l'ajout d'une supannPerson Réessayons un ldapsearch pour vérifier que supannPeople a bien été ajouté:

 pmarillonnet@condorcet:~$ ldapsearch -D "cn=admin,dc=condorcet,dc=dev,dc=entrouvert,dc=org" -w test -p 389 -h condorcet.dev.entrouvert.org -b "ou=supannPeople,dc=condorcet,dc=dev,dc=entrouvert,dc=org" -s sub "(ObjectClass=*)" * +
 # extended LDIF
 #
 # LDAPv3
 # base <ou=supannPeople,dc=condorcet,dc=dev,dc=entrouvert,dc=org> with scope subtree
 # filter: (ObjectClass=*)
 # requesting: debs devel Documents Maildir tmp tmp.txt var +
 #

 # supannPeople, condorcet.dev.entrouvert.org
 dn: ou=supannPeople,dc=condorcet,dc=dev,dc=entrouvert,dc=org
 structuralObjectClass: organizationalUnit
 entryUUID: 5ff39d3e-acd4-1036-82c9-7797aedf4f5c
 creatorsName: cn=admin,dc=condorcet,dc=dev,dc=entrouvert,dc=org
 createTimestamp: 20170403161436Z
 entryCSN: 20170403161436.022060Z#000000#000#000000
 modifiersName: cn=admin,dc=condorcet,dc=dev,dc=entrouvert,dc=org
 modifyTimestamp: 20170403161436Z
 entryDN: ou=supannPeople,dc=condorcet,dc=dev,dc=entrouvert,dc=org
 subschemaSubentry: cn=Subschema
 hasSubordinates: FALSE

 # search result
 search: 2
 result: 0 Success

 # numResponses: 2
 # numEntries: 1

maintenant : ajout d'une supannPerson inetOrgPerson ne définit aucun attribut obligatoire

quid de eduPerson et supannPerson ? le schema de eduPerson n'est disponible que sur des forums, pas de documentation officielle ?

les spéc de Internet2 ne contiennent pas de schéma...

https://www.internet2.edu/products-services/trust-identity/eduperson-eduorg/#service-overview laisse à croire que l'accès au schéma est disponible sur inscription seulement

update: schéma trouvé sur spaces.internet2.edu Le schéma est directement au format ldif compatible OpenLDAP Il suffit de l'ajouter à l'aide de ldapadd, maintenant que le mot de passe d'administration de l'annuaire a été défini

pmarillonnet@condorcet:~/Documents/supann$ ldapadd -x -D "cn=admin,cn=config" -w test -p 389 -h condorcet.dev.entrouvert.org -f ./openLdapEduPerson-201602KH.ldif
adding new entry "cn=eduPerson,cn=schema,cn=config"
ldap_add: Undefined attribute type (17)
    additional info: attributeType: attribute type undefined

TODO: identifier l'attribut dont le type est indéfini commenter ligne par ligne le ldif ? ldapmodified maintenant que l'entrée "cn=eduPerson,cn=schema,cn=config" a été ajoutée ?

Retrait de l'attribut eduPersonPrincipalNamePrior de la définition du schéma

On peut alors essayer d'ajouter une personne appartenant aux trois objectclasses inetOrgPerson, eduPerson, et supannPerson:

$ ldapadd -x -D "cn=admin,dc=condorcet,dc=dev,dc=entrouvert,dc=org" -w test -p 389 -h condorcet.dev.entrouvert.org -f ./Example_supann.ldif
adding new entry "uid=jmarrison,ou=supannPeople,dc=condorcet,dc=dev,dc=entrouvert,dc=org"

Ok pour la branche People

Maintenant: modifier l'IdP pour que le SSO engendre le transfert d'attributs SupAnn dans l'assertion SAML envoyée

Lecture de la doc: Tentative d'installer d'un authentic compatible SupAnn retours à la doc EO pour le projet PSL

d'après la doc, l'Idp se connecte en sortie au LDAP ? existe-t-il directement un connecteur LDAP dans authentic ? Pourquoi une telle connexion en sortie ? L'IdP ne communiquera pas directement avec le méta-annuaire django-mellon doit se charger d'aller récupérer les attributs nécessaires au méta-annuaire.

Piste envisageable Installer dans une VM l'ISO Debian fourni dans la doc et installer l'IDP Authentic2 compatible SupAnn => Déduire, voire exporter partiellement la configuration IDP SupAnn

Installation de VirtualBox et mise en place d'une VM IdP SupAnn On crée une nouvelle VM avec comme point de boot l'ISO télécharger sur la doc EO

Si cela ne fonctionne pas, configuration de l'OS en tant que domain 0 Xen -> plus lourd que virtualbox

Ok pour virtualbox, après installation de la dernière version du noyau et des entêtes On procède à l'installation IdP Authentic pour voir comment est géré le backend

Rien de concluant avec l'installation IdP nouvel essai avec la base installation

Rien de concluant, les dépôts ne sont plus à jour, les dépendances sont cassées

Comment résoudre le problème ?

Pistes de recherches envisageables :

  • IdP SAML SQLite (donc sans backend LDAP)
  • IdP SAML avec backend LDAP SupAnn

On privilégie d'abord la première solution sur l'IDP, on définit alors de nouveau attributs

Dans le cas d'un backend LDAP, les attributs utilisés auraient été directement déduits du schéma utilisé pour le stockage des utilisateurs

On crée pour ce faire une nouvelle politique d'options de fournisseur d'identité (SP options policy) prenant en compte les attributs nouvellement créés.

TODO Création d'un nouvel utilisateur comportant les différents attributs SupAnn Déploiement des deux autres branches (groupes et structures) de l'annuaire SupAnn, pour l'instant avec la seule branche People c'est un peu léger

répercussions du changement: django-mellon côté SP utils LDAP côté SP, à deux endroits (python-ldap et ldap3 ?) utils LDAP côté passerelle formulaire côté WCS

on va créer un nouvel utilisateur

Dans WCS, il faut aussi créer un nouveau formulaire qui tienne compte des attributs SupAnn creation du formulaire traitement_supann

BLOCKER: HTTP500 après merge d'une version à jour des sources est-ce l'installation globale dans /usr/lib qui a provoqué l'erreur

No module named authentic2.wsgi avec les sources locales

TODO se renseigner sur l'équivalent du path en python

Bad Gateway car le service ne semble pas écouter sur la socket qui lui est attribuée. Exploration des logs:

 # ls
 #

$ sudo mv authentic2-2.1.20.1134.g1fda65c.dirty-py2.7.egg/ ../.old

Procédure de rattrapage: départ à partir d'un nouveau git clone de l'IDP authentic création d'un branche locale pour la récupération des pulls ? pb : pas d'update des autres outils jusque là applications des changements nécessaires au déploiement ?

plusieurs solutions s'offrent à moi :

  • garder une version ancienne de l'IDP authentic (circa 12 mars)
  • mettre à jour tous les outils, au risque de casser le POC
  • ne mettre à jour que authentic, sous risque de péter l'appli

$ git diff 0de162732ac770 480c2374606 > deployment_changes.backup

pmarillonnet@condorcet:~/devel/authentic$ bash run.sh 
[2017-04-05 14:59:34 +0000] [4453] [INFO] Starting gunicorn 19.6.0
[2017-04-05 14:59:34 +0000] [4453] [INFO] Listening at: unix:/var/run/authentic2/authentic2.sock (4453)
[2017-04-05 14:59:34 +0000] [4453] [INFO] Using worker: sync
[2017-04-05 14:59:34 +0000] [4458] [INFO] Booting worker with pid: 4458
[2017-04-05 14:59:34 +0000] [4453] [INFO] Shutting down: Master
[2017-04-05 14:59:34 +0000] [4453] [INFO] Reason: Worker failed to boot.

Problème pour la réalisation des migrations : ./authentic2-ctl ne s'exécute plus correctement

pmarillonnet@condorcet:~/devel/authentic.bugged$ ./authentic2-ctl makemigrations
Traceback (most recent call last):
  File "./authentic2-ctl", line 4, in <module>
      import authentic2.logger
      ImportError: No module named authentic2.logger

décalage dans la structure des sources : authentic/src/authentic2 vs authentic/authentic2 ?

L'IDP fonctionne avec le déploiement à l'aide de sudo python setup.py install

Retour à la normale, mais persiste encore une erreur de fichiers statiques IDP en noir sur fond blanc...

pmarillonnet@condorcet:~/devel/authentic.deployed/src$ gunicorn authentic2.wsgi --bind unix:/var/run/authentic2/authentic2.sock
[2017-04-05 16:00:20 +0000] [6075] [INFO] Starting gunicorn 19.6.0
[2017-04-05 16:00:20 +0000] [6075] [INFO] Listening at: unix:/var/run/authentic2/authentic2.sock (6075)
[2017-04-05 16:00:20 +0000] [6075] [INFO] Using worker: sync
[2017-04-05 16:00:20 +0000] [6080] [INFO] Booting worker with pid: 6080
[2017-04-05 Wed 16:00:22] - - - WARNING py.warnings.<module>: /home/pmarillonnet/devel/authentic.deployed/src/authentic2_idp_openid/utils.py:8: RemovedInDjango19Warning: django.utils.importlib will be removed in Django 1.9.
  from django.utils.importlib import import_module

[2017-04-05 Wed 16:00:22]  - 06ce3442 ERROR django.request.handle_uncaught_exception: Internal Server Error: /admin/
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/django/core/handlers/base.py", line 108, in get_response
    response = middleware_method(request)
  File "/usr/lib/python2.7/dist-packages/django/middleware/locale.py", line 32, in process_request
    request, check_path=check_path)
  File "/usr/lib/python2.7/dist-packages/django/utils/translation/__init__.py", line 198, in get_language_from_request
    return _trans.get_language_from_request(request, check_path)
  File "/usr/lib/python2.7/dist-packages/django/utils/translation/trans_real.py", line 503, in get_language_from_request
    lang_code = request.session.get(LANGUAGE_SESSION_KEY)
  File "/usr/lib/python2.7/dist-packages/django/contrib/sessions/backends/base.py", line 59, in get
    return self._session.get(key, default)
  File "/usr/lib/python2.7/dist-packages/django/contrib/sessions/backends/base.py", line 181, in _get_session
    self._session_cache = self.load()
  File "/usr/lib/python2.7/dist-packages/django/contrib/sessions/backends/db.py", line 21, in load
    expire_date__gt=timezone.now()
  File "/usr/lib/python2.7/dist-packages/django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/django/db/models/query.py", line 328, in get
    num = len(clone)
  File "/usr/lib/python2.7/dist-packages/django/db/models/query.py", line 144, in __len__
    self._fetch_all()
  File "/usr/lib/python2.7/dist-packages/django/db/models/query.py", line 965, in _fetch_all
    self._result_cache = list(self.iterator())
  File "/usr/lib/python2.7/dist-packages/django/db/models/query.py", line 238, in iterator
    results = compiler.execute_sql()
  File "/usr/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 840, in execute_sql
    cursor.execute(sql, params)
  File "/usr/lib/python2.7/dist-packages/django/db/backends/utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/usr/lib/python2.7/dist-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/usr/lib/python2.7/dist-packages/django/db/utils.py", line 100, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/usr/lib/python2.7/dist-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/usr/lib/python2.7/dist-packages/django/db/backends/sqlite3/base.py", line 318, in execute
    return Database.Cursor.execute(self, query, params)
OperationalError: no such table: django_session

Pour l'instant on se contentera de cette installation, sans les fichiers statiques...

De nouveau la même erreur apparaît:

AssertionError at /admin/custom_user/user/add/

No exception message supplied

Request Method:     POST
Request URL:    http://idp-condorcet.dev.entrouvert.org/admin/custom_user/user/add/
Django Version:     1.8.16
Exception Type:     AssertionError
Exception Location:     /usr/local/lib/python2.7/dist-packages/authentic2-2.1.20.1149.g00bf793-py2.7.egg/authentic2/models.py in set_value, line 205
Python Executable:  /usr/bin/python

L'exécution de la commande sudo python setup.py clean révèle des incohérences de version

Cette commande ne recompilerait pas tous les bytecodes pyc après modification de la version d'une des dépendances du projet => découverte d'erreur après nettoyage des bytecodes de l'appli...

BLOCKER: mécanismes de migrations éclaté :

Running migrations:
  Applying authentic2_idp_oidc.0004_auto_20170405_1659... OK
Traceback (most recent call last):
  File "./authentic2-ctl", line 21, in <module>
    execute_from_command_line(sys.argv[:1] + argv)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/core/management/__init__.py", line 385, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/core/management/__init__.py", line 377, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/core/management/base.py", line 338, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/core/management/commands/migrate.py", line 165, in handle
    emit_post_migrate_signal(created_models, self.verbosity, self.interactive, connection.alias)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/core/management/sql.py", line 268, in emit_post_migrate_signal
    using=db)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/dispatch/dispatcher.py", line 198, in send
    response = receiver(signal=self, sender=sender, **named)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/contrib/contenttypes/management.py", line 39, in update_contenttypes
    for ct in ContentType.objects.using(using).filter(app_label=app_label)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/db/models/query.py", line 141, in __iter__
    self._fetch_all()
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/db/models/query.py", line 966, in _fetch_all
    self._result_cache = list(self.iterator())
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/db/models/query.py", line 265, in iterator
    for row in compiler.results_iter():
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/db/models/sql/compiler.py", line 701, in results_iter
    for rows in self.execute_sql(MULTI):
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/db/models/sql/compiler.py", line 787, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/db/backends/utils.py", line 81, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.8.16-py2.7.egg/django/db/backends/sqlite3/base.py", line 485, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such column: django_content_type.name

TODO: résoudre le pb de migrations patcher l'erreur sur le assert isinstance

pb réglé en installant la version 1.8 de Django plutôt qu'une sous-version précise (1.8.16 posait problème en l'occurrence)

Ok le patch sera pour plus tard incohérence entre la définition d'un attribut multiple et le moyen de saisie pour cet attribut (possibilité d'ajouter des champs), et le rendu final doit être un tuple, pas une chaîne de caractères

retour sur le déploiement: installation de l'IDP en mode de développement ? setup.py --dev

BLOCKER:ValueError: No JSON object could be decoded

erreur provoquée avec l'utilisateur admin FIX: création d'un nouvel utilisateur privilégié sudo ./authentic2-ctl createsuperuser

agent

Les attributs SupAnn ne sont pas transmis lors du SSO

(Pdb) p dir(UserSAMLIdentifier.objects.last().user)
['DoesNotExist', 'Meta', 'MultipleObjectsReturned', 'REQUIRED_FIELDS', 'USERNAME_FIELD', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', u'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', '__weakref__', '_base_manager', '_check_column_name_clashes', '_check_field_name_clashes', '_check_fields', '_check_id_field', '_check_index_together', '_check_local_fields', '_check_long_column_names', '_check_m2m_through_same_relationship', '_check_managers', '_check_model', '_check_ordering', '_check_swappable', '_check_unique_together', '_default_manager', '_deferred', '_do_insert', '_do_update', '_get_FIELD_display', '_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', '_get_pk_val', '_get_unique_checks', '_meta', '_perform_date_checks', '_perform_unique_checks', '_save_parents', '_save_table', '_set_pk_val', '_state', 'check', 'check_password', 'clean', 'clean_fields', 'date_error_message', 'date_joined', 'delete', 'email', 'email_user', 'first_name', 'from_db', 'full_clean', 'get_all_permissions', 'get_deferred_fields', 'get_full_name', 'get_group_permissions', 'get_next_by_date_joined', 'get_previous_by_date_joined', 'get_session_auth_hash', 'get_short_name', 'get_username', 'groups', 'has_module_perms', 'has_perm', 'has_perms', 'has_usable_password', 'id', 'is_active', 'is_anonymous', 'is_authenticated', 'is_staff', 'is_superuser', 'last_login', 'last_name', 'logentry_set', 'natural_key', 'objects', 'password', 'pk', 'prepare_database_save', 'refresh_from_db', 'saml_identifiers', 'save', 'save_base', 'serializable_value', 'set_password', 'set_unusable_password', 'unique_error_message', 'user_permissions', 'username', 'validate_unique']

Pdb côté mellon login.assertion.exportToXml()

FieldDoesNotExist at /accounts/mellon/login/ User has no field named 's_entite_affectation_principale' /usr/lib/python2.7/dist-packages/django/db/models/options.py in get_field, line 554

Incohérence dans le modèles de données de django_mellon le modèle semble cassé :

tpl     '{attributes[s_entite_affectation_principale][0]}'

old_value   u''

model_field     <django.db.models.fields.CharField: last_name>

Pourquoi last_name dans le model_field ? Pourtant les migrations du modèle ont été effectuées

Pistes de résolutions:

  • débogger le backend mellon ?
  • comprendre le déroulement de la fonction authenticate, pourquoi a-t-elle encore besoin d'aller taper dans le backend mellon
  • en parler avec Benj et Mik !
  • rollback vers un état stable ?

TODO: contourner le filtrage de port ssh chez moi !

Retour sur le bug de non transmission des attributs lors du SSO En réalité les attributs sont transmis, mais ne peuvent être stockés côté SP par mellon, qui semblent bloqué sur une incohérence du modèle User Quelle solution autre que le debugging ?

=> Etudier le customizing#extending the user model Sur conseil de Josué : mellon semble se contenter d'un modèle utilisateur par défaut, qui ne supporte pas l'ajout d'attributs tels que les attributs SupAnn que nous essayons de stocker côté SP

/usr/lib/python2.7/dist-packages/mellon/views.py in authenticate :

def authenticate(self, request, login, attributes): user = auth.authenticate(saml_attributes=attributes)

Bingo : class UserSAMLIdentifier(models.Model): user = models.ForeignKey( verbose_name=_('user'), to=settings.AUTH_USER_MODEL, related_name='saml_identifiers')

$ python manage.py makemigrations SystemCheckError: System check identified some issues:

ERRORS: saml.SupAnnUser.user_ptr: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out. HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.

//CURRENT

Explications techniques Mik

Se concentrer sur l'étude de synchro et d'approvisionnement en tant que telle La partie de mapping entre un événement déclenché et l'action WCS à effectuer mérite réflexions.

Dans quelle mesure le connecteur pourra être générique ? Les mêmes règles ne s'appliqueront-elles pas à tous les connecteurs ?

Le connecteur est en fait utilisé en écriture seulement : il sert à des fins d'approvisionnement et de synchronisation

Pour la lecture, un simple script ou outil de polling sera utilisé

Une des problématiques centrales à cette étude est la façon d'éviter les boucles/effets de bords provoqués par les changements en cascade sur les différents référentiels. Une modification effectuée par le système d'approvisionnement et de synchro ne doit pas être confondue avec une modification externe, nécessitant une éventuelle synchro avec d'autre référentiels

Plusieurs solutions s'offrent à nous pour remédier à ce problème :

  • garder une historique des actions (timestamp/horodatage) dans WCS pour ne pas les faire remonter lors du polling Cette solution nécessite une synchronisation de l'horloge des différentes briques logicielles de l'infra
  • utiliser un marqueur/flag du type performedByWCS pour chacunes des actions appliquées à un référentiel Le système de polling ne concernera que les actions ne portant pas le marqueur

=> TODO aller chercher un ou plusieurs scenario de processus en entreprise justifiant un outil de synchro Dans une deuxième phase, il faudra étudier ce qui serait déjà possible avec les outils EO tels quel

Recherche de scenarii de recours à la synchronisation :

  • documentation Alfresco
  • PapercutNG
  • LSC Pb : pas assez générique, pas d'expression des besoins de synchro

Lecture RFC4533 : LDAP Content Synchronization Operation Considérations justifiant une spéc du mécanisme de synchro avec LDAP :

  • pbatique de la convergence : comment s'assurer que les référentiels vont converger vers un état stable, sans données incohérentes Différents problèmes se posent avec les solutions déjà existantes :
    • le niveau de convergence souhaité ne peut être atteint
    • l'impossibilité d'une convergence reste indétectable
    • soit les hypothèses préalables à la synchro sont trop contraignantes
    • nécessite le stockage d'un historique des changements côté serveur
    • est à l'origine d'une quantité excessive d'informations échangées entre client et serveur

LDAP Sync simplement basé sur l'état actuel des serveurs, pas besoin d'un historique pour la reconstitution des modifications sur un des référentiels.

Cette RFC préconise aussi une optimisation en termes de quantité d'information nécessaire pour mener à bien la synchronisation.

Deux modes pour la détection des changements :

  • le polling mode : caractère ponctuel, granulaire de l'écoute Le serveur fournit un champ Sync State Control
  • le mode listening for changes (refreshAndPersist)

Operation selon un mode client-serveur ? TODO explication archi

  • explication des deux modes de connexion

Usages possibles :

  • application de type 'pages blanches' qui souhaitent synchronisation une sous-partie (un DIT partiel, pour Directory Information Tree) d'un annuaire plus global.
  • Moteur de méta-données récoltées par opérations de synchro sur des référentiels
  • Service de proxy-cache nécessitant la synchronisation pour construction du cache
  • Simple process esclave/maître pour la réplication cachée d'un DIT partiel (DIT fragment). Alternative à X.500 DISP (Directory

Elements entrant en jeu pour l'opération de synchronisation

  • syncUUID (codé sur 128 bits)
  • syncCookie
  • Sync Request Control
  • Sync State Control
  • Sync Done Control
  • Sync Information Message
  • Sync Result Code TODO explication fonctionnelle ou technique ? En quoi cela peut-il aider à la phase 2 de l'étude ?

Synchronisation des contenus

TODO Déclenchement de l'opération de synchronisation: Le serveur reçoit un message de type SearchRequest contenant un Search Request Control (cf plus haut TODO)

La détection d'une session déjà existante se fait par vérification de la présence d'un cookie dans la SearchRequest.

==========

//EN COURS TODO Plan Schémas Mise au propre Puis retour au travail technique

Découper en deux Description de l'existant Décrire fonctionnellement ce que l'on souhaite faire au niveau de la synchro Schémas du même type que ce qu'on a fait avec le campus condorcet (Diagramme de séquence, de flux : (RH, AD, téléphonie, méta-annuaire, outil de synchro, agent => 6 lignes) Puis on parlera des pbatiques techniques

=> Découpage en trois

Plan : partie 3 : "cas d'usages " - pbatique du stage, répondre à un besoin""" Commencer par une partie cas d'usage => aspect fonctionnel Etat de l'art : étude des différents techno Préliminaires de la GI = synthèse d'une page maxi sur les différents aspects, renvoyer vers les annexes pour les études détaillées

Partie 4 ajoutée Etat de l'art de la GI Etat de l'art sur la snchro et l'approvisionnement

Partie 5 Prise en main des technos DJango wcs passerelle les API rest

Partie 6 : Mise en oeuvre et realisations Chap 1 démonstrateur avec LSC Chap 2 développement spécifique cas campus condorcet, gestion des comptes invités chap 3 analyse de la couverture du besoin par les outils entr'ouvert architecture cible développements nécessaires

Synthèse technique (deux pages)

Conclusion (plus sur l'aspect stage)

Annnexes acronymes bibliographie (titre, source, date, auteurs) extrait de code source (il faut que ce soit pertinent, ou URLs vers un dépot public) diagramme et schémas ? Non dans les corps de chap

Exemple "haut-niveau"

//TODO doc commerciale des concurrents Cas d'usage pour la doc fonctionnelle A titre comparatif, la doc openidm est pas assez 'haut niveau'

Retour documentation midPoint : page 26: exemple complet IDM avec cas de synchro sur plusieurs bases d'identités creation modif avec répercussions dans les différentes bases suppression changement des droits

L'exemple, bien que non retenu pour l'étude expérimentale, présente certains point intéressants, méritants d'être détaillés ici :

Phase 1 : La procédure de synchro est effectuée par ajout d'une entrée dans le référentiel des ressources humaines. Cet ajout résulte de l'embauche d'une nouvelle employée. Le système est en charge de la génération d'attributs pour d'autres référentiels : la création d'un identifiant unique global est effectuée à partir du nom d'utilisateur local à la base RH. A la création de l'identifiant est associé l'ajout d'une entrée dans la base du gestionnaire d'identités (IDM). A ensuite lieu la récupération de l'identifiant organisationnel tel que renseigné lors de la création de l'entrée RH. Le gestionnaire d'identité peut ensuite déduire du service dans lequel se trouve la nouvelle employée. Il est aussi en charge de l'association des privilèges/droits associés au rôle du service auquel appartient maintenant l'employée. Ces rôles sont déduits du service qu'a rejoint l'employée. L'annuaire du service est un Active Directory (AD). L'ajout du compte est aussi accompagné de la création d'une boîte mail pour l'employée.

//Notion de groupes et de listes à étudier -> pour les mails seulement ? Finalement, la procédure est complétée par la création d'une entrée dans le CRM, en accord avec la politiques de permissions associées au rôle obtenu par l'employée.

Phase 2 : Dans cette phase, il est précisé que le gestionnaire d'identités peut effectuer une quelconque modification de privilèges indépendamment des rôles auxquels appartient un compte. Cette modification des privilèges résulte en la création d'un statut spécial, ne pouvant plus être défini comme la somme des rôles auxquels l'employée appartient. On retrouve une fois de plus la notion de workflow pour le mécanisme de gestion des identités : la montée en privilège n'est effectuée qu'une fois les approbations du manager et du responsable technique obtenues. De façon plus générale, l'aboutissement d'une demande de modifications de droits d'accèss nécessite l'action d'un opérateur (humain). Il s'agira ici d'un supérieur hiérarchique, lequel pourra accepter ou refuser la demande.

Phase 3 : Nous partons ici du cas d'un changement de nom de l'employée. Ce changement a des répercussions, de façon automatique et en cascade, sur les différents référentiels locaux à chaque service ou à chaque application. Par exemple, un changement de nom résulte logiquement en la création d'un nouvel alias d'adresse email. Cette création sera accompagnée de l'envoi d'un message de notification à l'employée concernant l'ajout de l'alias.

Phase 4 : L'expiration du mot de passe du compte utilisateur est aussi un mécanisme pouvant être pris en charge par le gestionnaire d'identité. Après choix d'un nouveau mot de passe par l'employée, le gestionnaire d'identité est en charge d'appliquer les modifications dans toutes les bases. Nous remarquons toutefois qu'à aucun moment on parle de SSO dans le cadre de cet exemple.

Phase 5 : Nous pouvons maintenant nous intéresser à des cas particuliers survenant dans le domaine de la gestion des identités numériques. Les besoins en sécurité dans le système d'informations requièrent la détection d'incohérences dans l'attribution des droits. Cette détection, pour l'exemple donné dans le document //REF// est mise en place à la suite de soupçons concernant un vol de données. Entre alors en compte la notion de traçabilité, en tant que possibilité d'identifier l'employé ayant attribué des droits excessifs à son subordonné à l'origine du vol de données. Le système de gestion des permissions doit ainsi être en mesure de répondre aux question suivantes :

  • Qui a attribué les droits ?
  • A quelle date ces droits ont-ils été données ?
  • Quelles actions ont été effectuées ensuite ?

La désactivation des droits est ensuite effectuée à l'aide du gestionnaire d'identités de façon centralisée, et est répercutée sur l'ensemble des référentiels d'identités.

Phase 6 : Nous passons maintenant au cas de la suppression de l'un des deux comptes, et de la diminution des droits associés à l'autre compte. Encore une fois des contraintes de synchronisation sont nécessaires pour assurer la cohérence des référentiels d'identités entre eux. Il ne faut pas, par exemple, que le rétablissement d'une sauvegarde, sur un référentiel local, et antérieure à la modification, ait pour conséquence d'annuler la suppression du compte banni.

Phase 7 : Il convient maintenant de décrire la procédure de mise en place d'une politique de sécurité, et ceci concernant en particulier la détection des droits incohérents, des comptes obsolètes ou n'ayant pas de propriétaire clairement identifié. Les besoins de sécurité impliquent la mise d'un processus de détection périodique de ces incohérences. //TODO essayer d'obtenir une estimation du temps nécessaire pour une telle détection, avec des paramètres standard ?

Phase 8 : Ce mécanisme de sécurité aboutit à la création d'une politique de recertification des droits de employés par chacun de leurs managers. Pour chaque employé, les droits activés jusqu'à présent doivent être validés à nouveau par un des responsables de l'employé (habilité à octroyer les droits en question).

Conclusion : Cet exemple met en scène différents concepts et processus pertinents dans le cadre de l'étude réalisée pour ce stage, notamment l'utilisation de workflows, et la synchronisation et l'approvisionnement à divers étapes du cycle de vie des données d'identités L'étape suivante consistera à identifier les contraintes techniques nécessaire au déploiement de telles fonctionnalités de gestion des identités, et de déterminer les éventuelles modifications nécessaires aux outils EO pour la mise en place d'un tel scenario.

Détails techniques GI

Un des concepts récurrents dans la gestion des identités est le RBAC (pour Role-Based Access Control). Ce terme est né des mécanismes souhaitant remédier aux inconvénients d'un contrôle d'accès par permissions simples. Dans un modèle régi par une politique de sécurité de type RBAC, on n'attribue pas des permissions aux utilisateurs, seulement des rôles. Une sécurisation des accès par RBAC présente deux principaux avantages :

  • il est nettement plus simple de manipuler des privilèges en termes de rôles, cette granularité reflète naturellement la séparation des responsabilités au sein d'une organisation (au sens où les permissions sont rarement données individuellement, mais sont plutôt associées au poste occupé par chaque individu).
  • ce modèle RBAC permet la factorisation des permissions à travers les rôles : c'est plus maintenable qu'un éclatement des permissions sur chaque utilisateur.

Nous précisons toutefois que des alternatives au modèle RBAC existent, l'une d'elle étant ABAC (Attribute-Based Access Control). Ce mécanisme manipule un ensemble d'attributs permettant de générer à la volée les permissions ? Les auteurs du document //REF// affirment toutefois qu'un contrôle de type ABAC n'est pas adapté dans le cadre d'un SI comportant un gestionnaire d'identités.

Planification du stage

La planification du stage est réalisée à l'aide d'un ensemble de diagrammes de Gantt : Ils sont au total au nombre de quatre, c'est-à-dire les diagrammes :

  • prévisionnel, i.e. réalisé au début du stage
  • réel. C'est celui qui est maintenu à jour tout au long du projet
  • prévisionnel mi-parcours, réalisé à la moitié de la durée du projet
  • final. C'est planning réel une fois le projet réalisé.

Ecriture d'un connecteur Passerelle

La création d'un nouveau connecteur doit d'abord être précédée d'une phase de lecture du code de Passerelle, afin de comprendre la structuration des connecteurs fournis par l'application.

Choix d'un connecteur à dériver pour l'écriture du connecteur LDAP

Update : L'outil Passerelle est pensé pour faciliter le développement de nouveaux connecteurs. Seule l'écriture du fichier models.py est nécessaire. Il suffit de préciser les endpoints mis à disposition par le connecteur, et passerele se charge du code 'logique' (non métier) du connecteur.

Mise au point technique

Python

Packing et unpacking

Coding style

  • keywork linebreaks
  • cleaned_data pour les formulaires
  • surcharge de __unicode__ et __str__ pour la description textuelle des données et objets Django.

"A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is the most important." (PEP8)

Lecture du code source Authentic

Sessions et pseudo-terminaux

tmux

Pb: bugs

screen

Possibilité de détacher les sessions Plus puissant que tmux mais plus difficile d'utilisation

Virtualisation

Avantages

TODO Securité, portabilité, 'scalabilité' etc

OpenVZ

Techno utilisée pour la virtualisation des serveurs sur la plateforme de développement (hébergée chez OVH) OpenVZ implémenté sa propre version du noyau (on parle de noyau 'patché'), lui-même basé sur le noyau RHEL Notion de VPS (Virtual Private Server) ou de VE (Virtual Environment) Identification des conteneurs par attribution d'un VEID VE IDentifier

Notion de "conteneurisation" : hôte et invités partagent un même noyau

Gestion des conteneurs par CLI (Command-Line Interface) Utilitaire vzctl {start, create, stop, exec, enter, set} <params>

Bâti sur LXC ? cgroups ?

Création d'un conteneur suivant la technique de template cache : Il s'agit d'un patron de système d'exploitation, nécessaire au déploiemend'un nouveau conteneur

TODO OS template metadata

TODO en quoi cela diffère-t-il des 'recipes' Docker et Rocket ?

Packaging

Cette section couvrira la méthode de packaging utilisée chez EO: création de paquets Debian pour les projets Django développés par l'équipe l'outil utilisé pour la création de ces paquets .deb (cf deb.entrouvert.org) est dpkg-deb Il a recours à l'utilitaire fakeroot (pourquoi ?)

Pour chaque projet, les scripts et metadonnées nécessaires à la création du paquet sont situées dans le fichier /debian

Les sources des projets EO fournissent aussi des exemples de fichier de configuration pour les services associées (Apache, nginx, gunicorn, systemd, postgresql) //TODO a verifier

Structure d'un paquet Debian

Le fichier control rassemble les méta-données du paquet

Scripts preinst, poistinst, prerm, postrm

commande dpkg-deb --build

Linux screen

Abstraction des shells en session ssh, avec possibilité de séparer la fenêtre active en plusieurs shell, de détacher les screen de la session, afin de pouvoir les récupérer lors de la prochaine connexion.

Connecteurs

ConnId

Javadoc at http://connid.tirasa.net/apidocs/1.4/index.html TODIG ?

Puppet

Il s'agit d'un outil de gestion de config logicielle, utilisé pour l'automatisation du déploiement des serveurs. Reprend les principes du contrôle de version du code pour l'adapter à la config serveur Voir comment EO l'utilise pour le déploiement de ses serveurs de dev et de prod

GnuPG (Privacy Guard)

Implémentation GNU de PGP (Pretty Good Privacy)

Lecture de la RFC : points remarquables :

compression has the added side effect that some types of
   attacks can be thwarted by the fact that slightly altered, compressed
      data rarely uncompresses without severe errors.  This is hardly
         rigorous, but it is operationally useful.

Radix-64 ~ ASCII Armor

Le chiffrement mais surtout la signature : fonctionnalité clé de GnuPG

Fonctionnalités de conversion S2K (String to Key)

TODO Paramétrer la signature des messages avec GnuPG La notion de fiabilité de la clé est définie par le nombre de certifications par des tiers.

Config client VoIP

TODO

Sources

https://shibboleth.net/

Lues

A lire

https://docs.djangoproject.com/fr/1.10/topics/settings/ http://support.novell.com/techcenter/articles/ana20011101.html http://www.journaldunet.com/developpeur/xml/analyse/la-federation-d-identite-au-travers-de-saml.shtml https://www.ietf.org/rfc/rfc4512.txt https://docs.djangoproject.com/en/1.10/howto/custom-template-tags/#thread-safety-considerations http://syncope.apache.org/docs/reference-guide.html https://en.wikipedia.org/wiki/ALFA_%28XACML%29 https://en.wikipedia.org/wiki/List_of_LDAP_software

Annexes

Assertion SAML d'authentification (SAMLResponse IdP -> SP)

<?xml version="1.0"?> <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_CD4CC621A02FDE6054649B69E6DBCC41" InResponseTo="_A79D6A8E4A93A92D65EE570ECA571BDB" Version="2.0" IssueInstant="2017-02-15T14:14:04Z" Destination="http://localhost:8008/accounts/mellon/login/" Consent="urn:oasis:names:tc:SAML:2.0:consent:prior"> <saml:Issuer>http://localhost:8000/idp/saml2/metadata</saml:Issuer> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">\n<SignedInfo>\n<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>\n<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>\n<Reference URI="#_CD4CC621A02FDE6054649B69E6DBCC41">\n<Transforms>\n<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>\n<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>\n</Transforms>\n<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>\n<DigestValue>ozqrnvN5HCJ8jxnPK8oT8U/+sHk=</DigestValue>\n</Reference>\n</SignedInfo>\n<SignatureValue>Ccne2rcykuXTgGW8QSNCANcliOvvl854uyiwPXGTGYbKfDNrFq87HNmDDizLslDY\nZVETw6TdVRi6vKlHebW0uWO9F4XRy7o4qEGiIEhLLGe1MIz+PWKqd1G1FcoQcEVG\nojZioS1BfWxcySZrU/OXftIsW929wYeXV+FsHauihGolAp5tnf+e0es5Gk2kuawy\nLBSEoWtriXRVMpEDfl1BHM61Y1uzkpmeA221e07WLDLr/KuAf4PS0px7l8YUEDz4\nA87GHekQ8ar2OiS+9unJ9DhZ+qFzLeddb6IdxHqUfWkdmAdajGffAyvfefEcm5wp\njE2b6cQPv0xh530CEFRXUw==</SignatureValue>\n<KeyInfo>\n<X509Data>\n<X509Certificate>MIIDIzCCAgugAwIBAgIJANUBoick1pDpMA0GCSqGSIb3DQEBBQUAMBUxEzARBgNV\nBAoTCkVudHJvdXZlcnQwHhcNMTAxMjE0MTUzMzAyWhcNMTEwMTEzMTUzMzAyWjAV\nMRMwEQYDVQQKEwpFbnRyb3V2ZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEAvxFkfPdndlGgQPDZgFGXbrNAc/79PULZBuNdWFHDD9P5hNhZn9Kqm4Cp\n06Pe/A6u+g5wLnYvbZQcFCgfQAEzziJtb3J55OOlB7iMEI/T2AX2WzrUH8QT8NGh\nABONKU2Gg4XiyeXNhH5R7zdHlUwcWq3ZwNbtbY0TVc+n665EbrfV/59xihSqsoFr\nkmBLH0CoepUXtAzA7WDYn8AzusIuMx3n8844pJwgxhTB7Gjuboptlz9Hri8JRdXi\nVT9OS9Wt69ubcNoM6zuKASmtm48UuGnhj8v6XwvbjKZrL9kA+xf8ziazZfvvw/VG\nTm+IVFYB7d1x457jY5zjjXJvNysoowIDAQABo3YwdDAdBgNVHQ4EFgQUeF8ePnu0\nfcAK50iBQDgAhHkOu8kwRQYDVR0jBD4wPIAUeF8ePnu0fcAK50iBQDgAhHkOu8mh\nGaQXMBUxEzARBgNVBAoTCkVudHJvdXZlcnSCCQDVAaInJNaQ6TAMBgNVHRMEBTAD\nAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAy8l3GhUtpPHx0FxzbRHVaaUSgMwYKGPhE\nIdGhqekKUJIx8et4xpEMFBl5XQjBNq/mp5vO3SPb2h2PVSks7xWnG3cvEkqJSOeo\nfEEhkqnM45b2MH1S5uxp4i8UilPG6kmQiXU2rEUBdRk9xnRWos7epVivTSIv1Ncp\nlG6l41SXp6YgIb2ToT+rOKdIGIQuGDlzeR88fDxWEU0vEujZv/v1PE1YOV0xKjTT\nJumlBc6IViKhJeo1wiBBrVRIIkKKevHKQzteK8pWm9CYWculxT26TZ4VWzGbo06j\no2zbumirrLLqnt1gmBDvDvlOwC/zAAyL4chbz66eQHTiIYZZvYgy</X509Certificate>\n</X509Data>\n</KeyInfo>\n</Signature> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion Version="2.0" ID="_A86605DF1F9D51A8BD5EFB5F9B02A712" IssueInstant="2017-02-15T14:14:10Z"> <saml:Issuer>http://localhost:8000/idp/saml2/metadata</saml:Issuer> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">\n<SignedInfo>\n<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>\n<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>\n<Reference URI="#_A86605DF1F9D51A8BD5EFB5F9B02A712">\n<Transforms>\n<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>\n<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>\n</Transforms>\n<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>\n<DigestValue>F9UyV7kkrdL45HhZmIG+qR8hqE8=</DigestValue>\n</Reference>\n</SignedInfo>\n<SignatureValue>cmFamTX6vzK0evsehNv8U7Mjz1JXdz60ZGpzEuner+xEdB8I4rISzWZBLmLQYMiU\n8IlCZYvOeaeHIwf/xStowUZy+dfjzYKMmN5OD9z9ifD5Kr6rNNS9a0Tsmu55HUvv\nD83CkGS2c8HsdpWTR3Og7ED2lVT6rsXTx+VgTJ1mzl0ONVKPSnTp8x09VgHbMFXh\nLq5Pg+5im+G0jJIcpVN3VesVzLdfP6w3CjJz5f+aMllfvRdYYSad0vyXlLUx59Al\nAsIeqFTFq3uKsVHH4yd/JZoFwrhFE4Q6Ve9UeTRw9qR+y6M+fd/cJTcvFzHjKo2A\nTEt9QYM4RpfPPy4conjGqg==</SignatureValue>\n<KeyInfo>\n<X509Data>\n<X509Certificate>MIIDIzCCAgugAwIBAgIJANUBoick1pDpMA0GCSqGSIb3DQEBBQUAMBUxEzARBgNV\nBAoTCkVudHJvdXZlcnQwHhcNMTAxMjE0MTUzMzAyWhcNMTEwMTEzMTUzMzAyWjAV\nMRMwEQYDVQQKEwpFbnRyb3V2ZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEAvxFkfPdndlGgQPDZgFGXbrNAc/79PULZBuNdWFHDD9P5hNhZn9Kqm4Cp\n06Pe/A6u+g5wLnYvbZQcFCgfQAEzziJtb3J55OOlB7iMEI/T2AX2WzrUH8QT8NGh\nABONKU2Gg4XiyeXNhH5R7zdHlUwcWq3ZwNbtbY0TVc+n665EbrfV/59xihSqsoFr\nkmBLH0CoepUXtAzA7WDYn8AzusIuMx3n8844pJwgxhTB7Gjuboptlz9Hri8JRdXi\nVT9OS9Wt69ubcNoM6zuKASmtm48UuGnhj8v6XwvbjKZrL9kA+xf8ziazZfvvw/VG\nTm+IVFYB7d1x457jY5zjjXJvNysoowIDAQABo3YwdDAdBgNVHQ4EFgQUeF8ePnu0\nfcAK50iBQDgAhHkOu8kwRQYDVR0jBD4wPIAUeF8ePnu0fcAK50iBQDgAhHkOu8mh\nGaQXMBUxEzARBgNVBAoTCkVudHJvdXZlcnSCCQDVAaInJNaQ6TAMBgNVHRMEBTAD\nAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAy8l3GhUtpPHx0FxzbRHVaaUSgMwYKGPhE\nIdGhqekKUJIx8et4xpEMFBl5XQjBNq/mp5vO3SPb2h2PVSks7xWnG3cvEkqJSOeo\nfEEhkqnM45b2MH1S5uxp4i8UilPG6kmQiXU2rEUBdRk9xnRWos7epVivTSIv1Ncp\nlG6l41SXp6YgIb2ToT+rOKdIGIQuGDlzeR88fDxWEU0vEujZv/v1PE1YOV0xKjTT\nJumlBc6IViKhJeo1wiBBrVRIIkKKevHKQzteK8pWm9CYWculxT26TZ4VWzGbo06j\no2zbumirrLLqnt1gmBDvDvlOwC/zAAyL4chbz66eQHTiIYZZvYgy</X509Certificate>\n</X509Data>\n</KeyInfo>\n</Signature> <saml:Subject> <saml:NameID NameQualifier="http://localhost:8000/idp/saml2/metadata">_1E83322C6A38FF13CF515D299647E04E</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData NotOnOrAfter="2017-02-15T14:15:10.325204Z" Recipient="http://localhost:8008/accounts/mellon/login/" InResponseTo="_A79D6A8E4A93A92D65EE570ECA571BDB"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2017-02-15T14:13:10.325204Z" NotOnOrAfter="2017-02-15T14:15:10.325204Z"> <saml:AudienceRestriction> <saml:Audience>http://localhost:8008/accounts/mellon/metadata/</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2017-02-15T14:14:10.325204Z" SessionIndex="_A86605DF1F9D51A8BD5EFB5F9B02A712" SessionNotOnOrAfter="2017-03-01T14:14:10Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="id_test" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" FriendlyName="Test ID"> <saml:AttributeValue>2</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="lname_test" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" FriendlyName="Test Last Name"> <saml:AttributeValue>Marillonnet</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="fname_test" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" FriendlyName="Test First Name"> <saml:AttributeValue>Paul</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion> </samlp:Response>

Diagramme de séquence conceptuel du POC

TODO

Diagramme de séquence technique du POC

TODO

Architecture fonctionnelle du POC

TODO

Architecture logicielle du POC

TODO

Prises de notes vidéos

Workshop: Identity standards OIDC

OAuth

TODO

OpenID Connect

Notion de Authentication Context 4 degrés de sécurité ? acr : notion de risque, de seuil de risque de acceptable amr : TODO

Réauthentification forcée Durée de la vie la session pour une machine

Lier seuil de risque et activité liée à l'authentification (1:14) Même contraintes et problèmes qu'avec SAML2

Requête d'autorisation dynamique (1:15)

JSON Web Tokens (RFC7519) -> Introduit la notion de confirmation (utilisateur ?) JWS RFC7515 JSON Web Signature JWE RFC7516 JSON Web Encryption

NAPPS PKCE ('pixy') AC/DC

Archi en 3 parties: Client Resource server Authorization Server

Pour le scenario de livraison d'un jeton (token)

Cf Google Access Tokens Nécessite de PKCE pour remédier à ce type d'attaque dans les applis natives frauduleuses

IOS9: Mutual authentication ? Access aux cookies partagés dans le navigateur pour le SSO Sans agent natif de jetons (Native tokan agent)

ACDC est un type de JSON Web Token //TODIG code verifier (hash) code challenge (salt ?) Génération d'un nombre aléatoire

RT & AT Access Token Replay Token ? Resource Token ? Revocation token ? TLS Token Auth {SaaS, Enterprise} Authentication Server

concepts clé :

  • NAPPS Token agent directement sur le terminal client
  • PKCE
  • Authorization Cross Domain Code (ACDC)

SAML

1.0 1.1 2.0 -> 2005

XML SAOP XML Signature

techno pre OIC et OAuth

les spécifications de la RFC sont ambigües variations lors de l'implémentation

Quelles implémentations ? 8 documents différents forment la totalité de l'implémentation Fonctionnalités optionnelles peuvent être imposées par les bindings SAML

SAOP, XML : mastodontes

Problèmes sémantiques de XML : pas interopérable

binding le plus populaire: SAML Redirect & POST Facile à implémenter, et à déployer Chiffrement des messages SAML optionnel seulement

SAML Artifact en deux étapes envoi d'une référence sur un premier canal le message passe sur un second canal plus difficile à déployer apparence de la sécurité seulement ? authentification du second canal devient nécessaire déplacement du problème ?

SSO: initié par l'IDP ou par le SP

Si initié par l'IDP URL, visitée par le SP, qui génère une assertion SAML

initié par le SP Pb de la découverte du fournisseur d'identité

Signed Authent request pbatique de l'échange des certificats, sans retarder le sso

DoS potentiel vers le fournisseur de service 2 sessions : d'application

  • une session pour l'IDP

Profils d'implémentation de déploiement (contenu dans le profil précédent)

SAML2Int

Notion avancées : Découverte de fournisseur d'identité laisser le choix parmi une liste d'IDP à l'utilisateur

NASCAR Screen

wayf-less URLs

ECP Enhanced Client or Proxy

SLO plus difficile que SSO Comment garantir le SLO ? l'ACK du SP quant au SLO ? Faille de sécurité potentielle si échec du SLO Best practice : ne pas implémenter SLO Pas le même problème avec le SSO : s'il échoue ce n'est pas grave du point de vue de la sécurité

La fermeture du navigateur Web détruit les cookies de session

Confiance entre IDPs et SPs Quelle politique de sécurité de l'IDP auquel le SP fait confiance ? Vice versa : comment s'assurer, du point de vue de l'IDP, que le SP ne fait pas n'importe quoi avec les infos d'identité envoyées ?

Aller voir les spec de l'échange de métadonnées Origine des métadonnées à vérifier utilisation l'option d'expiration de la période de validité des métadonnéesn

Signature XML : d'abord le décodage du fichier XML => DOS

Echecs de SAML: simpleSAML php demo cert : à fuir

wrapping attack

Au contraire Cross domain sso très utilisé //TODIG

TODO téléchargement des deux autres vidéos DONE

Faire une synthèse des deux