======== Re2o ======== Soft inter asso de gestion users et reseau. Cf [[https://slides.rezometz.org/re2o.html]] ===== Utilité pour federez ===== L'ancien webldap (en django également) a rendu de très grand services, mais il fallait le maintenir. Autre problème, il n'utilisait pas les models, il fallait tout coder à la main dans les views, ce qui faisait que chaque fonctionnalité nécessitait beaucoup de code. L'idée d'utiliser une instance de re2O est déjà de ne plus avoir à maintenir un webldap, mais surtout d'avoir plus de fonctionnalités. (gestion des machines de federez, des assos, du dns, etc etc) ===== Instalation ===== ==== Démarrage ==== Sur dodecagon : Suivre le readme.sh; on aurait pu utiliser le script d'install auto, mais on a fait les choses à la main ici. On clone le dépot [[https://gitlab.federez.net/federez/re2o.git]] dans /var/www/re2o. On installe toutes les dépendances avec apt et pip3, suivre le readme pour cela : apt install python3-django python3-dateutil texlive-latex-base texlive-fonts-recommended python3-djangorestframework python3-django-reversion python3-pip libsasl2-dev libldap2-dev libssl-dev pip3 install django-bootstrap3 django-ldapdb django-macaddress ==== Bdd ==== On choisi mysql en local comme base de donnée django. On initialise la bdd : apt install python3-mysqldb mysql-client CREATE DATABASE re2o collate='utf8_general_ci'; CREATE USER 're2o'@'localhost' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON re2o.* TO 're2o'@'localhost'; FLUSH PRIVILEGES; ==== Ldap ==== Vu qu'on migre depuis l'ancien, dans un premier temps on met le ldap sur un autre serveur (federez-test) puis on switchera après. L'installation du ldap est toujours la même, on copie schema.ldiff et db.ldiff depuis le depot. Ensuite on remplace dans les fichiers dc=example,dc=org par dc=federez, dc=net, ainsi que FILL_IT par le hash du mdp ldap qu'on choisi. On rajoute le ssl avec olcTLSCertificateKeyFile: /etc/letsencrypt/live/federez.net/privkey.pem olcTLSCACertificateFile: /etc/letsencrypt/live/federez.net/chain.pem olcTLSCertificateFile: /etc/letsencrypt/live/federez.net/cert.pem ` dans schema.db , enfin : service slapd stop rm -rf /etc/ldap/slapd.d/* rm -rf /var/lib/ldap/* slapadd -n 0 -l schema.ldiff -F /etc/ldap/slapd.d/ slapadd -n 1 -l db.ldiff chown -R openldap:openldap /etc/ldap/slapd.d chown -R openldap:openldap /var/lib/ldap service slapd start ===== Configuration ===== On crée le settings_local.py, à partir de settings_local.example.py. On rempli le mdp bdd et ldap. On applique les migrations, python3 manage.py migrate, ça prend du temps. On crée un premier un super user avec python3 manage.py createsuperuser ===== Serveur web ===== On utilise apache, voici la config : ServerName re2o.federez.net ServerAlias re2o webldap webldap.federez.net Redirect "/" "https://re2o.federez.net/" ServerName re2o.federez.net ServerAlias re2o webldap webldap.federez.net LogLevel warn ErrorLog ${APACHE_LOG_DIR}/re2o-error.log CustomLog ${APACHE_LOG_DIR}/re2o-access.log combined Alias /static /var/www/re2o/static_files WSGIScriptAlias / /var/www/re2o/re2o/wsgi.py WSGIProcessGroup re2o WSGIDaemonProcess re2o processes=2 threads=16 maximum-requests=1000 display-name=re2o SSLCertificateFile /etc/letsencrypt/live/federez.net/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/federez.net/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf On peut à présent se connecter sur re2o.federez.net avec le compte qu'on a crée. ===== Migration depuis l'ancien ldap ===== Les anciennes données étaient dans l'ancien ldap sur dodecagon, il a été nécessaire de transéferer tout le monde. On utilise python3-ldap3 pour chercher et trouver les informations dans le ldap. Pour info, voici comment on a procédé : === Transfert des users === from ldap3 import Server,Connection,ALL_ATTRIBUTES, ALL conn = Connection(server, 'cn=admin,dc=federez,dc=net', 'pkop', auto_bind=True) conn.search('ou=users,dc=federez,dc=net', '(objectclass=inetOrgPerson)', attributes=ALL_ATTRIBUTES) entries = conn.entries In [79]: from users.models import Adherent, ListShell In [78]: for en in ent: ...: adh = Adherent() ...: adh.pseudo = str(en.cn) ...: if len(str(en.displayName).split())>1: ...: adh.surname = str(en.displayName).split()[1] ...: adh.name = str(en.displayName).split()[0] ...: else: ...: adh.surname = str(en.displayName) ...: adh.name = str(en.displayName) ...: adh.email = str(en.mail) ...: if hasattr(en, 'loginShell'): ...: adh.shell, created = ListShell.objects.get_or_create(shell=str(en.loginShell)) ...: if hasattr(en, 'uidNumber'): ...: adh.uid_number = str(en.uidNumber) ...: if hasattr(en, 'sambaNTPassword'): ...: adh.sambaNTPassword = en.sambaNTPassword ...: if hasattr(en, 'userPassword'): ...: adh.password = str(en.userPassword.value.decode("utf-8")[:6]) + '$' + str(en.userPassword.value.decode("utf-8")[6:]) ...: adh.save() === Transfert des services-users (bind ldap pour les services) === conn.search('ou=service-users,dc=federez,dc=net', '(objectclass=simpleSecurityObject)', attributes=ALL_ATTRIBUTES) entries = conn.entries In [87]: for en in entries: ...: s = ServiceUser() ...: s.pseudo = str(en.cn) ...: s.password = str(en.userPassword.value.decode("utf-8")[:6]) + '$' + str(en.userPassword.value.decode("utf-8")[6:]) ...: s.save() === Transfert des assos === A la main, il n'y en avait pas 150 === Transfert des groupes/liens users-asssos === Plus compliqué, il a fallu extraire le pseudo depuis l'objet member of dans les groupes, les jointures n'existant évidemment pas en ldap. from users.models import User, Adherent, Club conn.search('ou=associations,dc=federez,dc=net', '(objectclass=groupOfUniqueNames)', attributes=ALL_ATTRIBUTES) entries = conn.entries In [1]: for ent in entries: ...: club_instance = Club.objects.get(pseudo=str(ent.o)) ...: if hasattr(ent, 'owner'): ...: for own in ent.owner: ...: uid = conn.search('ou=users,dc=federez,dc=net', '(%s)' % str(own.split(',')[0]), attributes=ALL_ATTRIBUTES) ...: user = conn.entries[0] ...: user_instance = Adherent.objects.get(pseudo=str(user.cn)) ...: club_instance.administrators.add(user_instance) ...: if hasattr(ent, 'uniqueMember'): ...: for memb in ent.uniqueMember: ...: uid = conn.search('ou=users,dc=federez,dc=net', '(%s)' % str(memb.split(',')[0]), attributes=ALL_ATTRIBUTES) ...: user = conn.entries[0] ...: user_instance = Adherent.objects.get(pseudo=str(user.cn)) ...: club_instance.members.add(user_instance)