Table des matières
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 :
<VirtualHost *:80> ServerName re2o.federez.net ServerAlias re2o webldap webldap.federez.net Redirect "/" "https://re2o.federez.net/" </VirtualHost> <VirtualHost *:443> 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 </VirtualHost>
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)