Préparation de la migration

Nettoyage domaine wiki.auf.org (poste du travail)

Copier les patchs (du poste de travail vers le serveur) :

scp -pr moin-migration root@wiki.auf.org:

Se connecter au serveur :

ssh root@wikibeta.auf.org

Migration

Paquet Debian :

apt-get install python-moinmoin

Migration de la configuration :

service apache2 stop
mv /etc/moin/farmconfig.py /etc/moin/farmconfig.py-dist
mv -i /etc/moinmoin/* /etc/moin/
rmdir /etc/moinmoin/

Petits fixes pour permettre une future migration ou éviter messages d'erreur d'apache :

cp -a /var/lib/moinmoin/wikiteki/data/meta /var/lib/moinmoin/glossairedlc/data/
cp -a /usr/share/moin/htdocs/modernized/css/projection.css  /var/www/europython-glossairedlc/css/

cat <<EOT>> /etc/moin/wikilist
www-data https://wiki.auf.org/wikiteki/
www-data https://wiki.auf.org/wikiwysiwyg/
www-data https://wiki.auf.org/communauteutilisateurs/
www-data https://wiki.auf.org/glossairedlc/
EOT

Effacement du moin ancien :

rm /usr/local/bin/moin
rm -fr /usr/local/lib/python2.4 /usr/local/lib/python2.5
rmdir /usr/local/lib/python2.6/site-packages/
rm /usr/local/lib/python2.6/dist-packages/moin-1.9.3-py2.6.egg-info
rm -fr /usr/local/lib/python2.6/dist-packages/MoinMoin/
mv /etc/moin/moin.wsgi ~/

Configuration d'Apache http (redirection vers https) :

cat <<EOT> /etc/apache2/sites-available/wiki.auf.org
<VirtualHost *:80>
        ServerName wiki.auf.org
        ServerAdmin technique@ca.auf.org
        Redirect permanent / https://wiki.auf.org/
</VirtualHost>
EOT

Configuration d'Apache https :

cat <<EOT> /etc/apache2/sites-available/wiki.auf.org-ssl
<VirtualHost *:443>
        ServerName  wiki.auf.org
        ServerAdmin technique@ca.auf.org

        DocumentRoot /var/www/

        <Directory />
                Options None
                AllowOverride None
        </Directory>

        <Directory /var/www/>
                Options None
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

        Alias /favicon.ico /var/www/favicon.ico
        #Alias /wikiteki/favicon.ico /var/www/favicon.ico
        #Alias /wikiwysiwyg/favicon.ico /var/www/favicon.ico
        #Alias /glossairedlc/favicon.ico /var/www/favicon.ico
        #Alias /communauteutilisateurs/favicon.ico /var/www/favicon.ico

        WSGIScriptAlias /wikiteki /usr/share/moin/server/moin.wsgi
        WSGIScriptAlias /wikiwysiwyg /usr/share/moin/server/moin.wsgi
        WSGIScriptAlias /communauteutilisateurs /usr/share/moin/server/moin.wsgi
        WSGIScriptAlias /glossairedlc /usr/share/moin/server/moin.wsgi

        Alias /polycom          /var/www/polycom

        Alias /static/gugiel                    /var/www/gugiel
        Alias /static/moniker                   /var/www/moniker
        Alias /static/europython                /var/www/europython
        Alias /static/europython-wikiwysiwyg    /var/www/europython-wikiwysiwyg
        Alias /static/europython-glossairedlc   /var/www/europython-glossairedlc
        Alias /static/comments.css              /var/www/europython-glossairedlc/css/comments.css
        Alias /static/                          /usr/share/moin/htdocs/
#       Alias /moin_static194/                  /usr/share/moin/htdocs/
        <Directory /usr/share/moin/htdocs>
                Options None
                AllowOverride None
                order allow,deny
                allow from all
        </Directory>

        RedirectMatch permanent ^/*$  https://wiki.auf.org/wikiteki/

        ErrorLog /var/log/apache2/error.log
        LogLevel warn
        CustomLog /var/log/apache2/access.log combined
        ServerSignature Off

        SSLEngine on
        SSLCertificateFile /etc/ssl/certs/_.auf.org-cert.pem
        SSLCertificateKeyFile /etc/ssl/private/_.auf.org-key.pem
        SSLCACertificateFile /etc/ssl/certs/GandiStandardSSLCA.pem
        SSLVerifyClient None
</VirtualHost>
EOT

Desactiver / Activer sites Apache :

a2dissite 00-wiki
a2ensite wiki.auf.org wiki.auf.org-ssl
service apache2 start

Conf ID AuF (mod_mellon) pour Sikiteki

Les boutons ID AuF :

cd /var/www/
wget -N https://nuage.auf.org/themes/auf/core/img/idauf_bouton.png
wget -N https://nuage.auf.org/themes/auf/core/img/idauf_bouton_survol.png

Le hack pour ajouter auth mellon + le bouton ID dans le login :

cd /etc/moin/
cp -a ~/moin-migration/wikiteki.py.patch .
patch wikiteki.py < wikiteki.py.patch && rm wikiteki.py.patch

Contenu du fichier /etc/moin/wikiteki.py.patch :

--- wikiteki.py.orig    2015-02-18 09:51:02.423125648 -0500
+++ wikiteki.py 2015-02-20 10:58:30.113002603 -0500
@@ -15,6 +15,148 @@
 # we import the FarmConfig class for common defaults of our wikis:
 from farmconfig import FarmConfig
 
+#####################################################################FIXME
+import urllib
+
+from MoinMoin.user import get_by_email_address
+from MoinMoin import log
+from MoinMoin import user, wikiutil
+logging = log.getLogger(__name__)
+
+
+class LoginReturn(object):
+    """ LoginReturn - base class for auth method login() return value"""
+    def __init__(self, user_obj, continue_flag, message=None, multistage=None,
+                 redirect_to=None):
+        self.user_obj = user_obj
+        self.continue_flag = continue_flag
+        self.message = message
+        self.multistage = multistage
+        self.redirect_to = redirect_to
+
+class ContinueLogin(LoginReturn):
+    """ ContinueLogin - helper for auth method login that just continues """
+    def __init__(self, user_obj, message=None):
+        LoginReturn.__init__(self, user_obj, True, message=message)
+
+class MellonAuth:
+    name = 'mellon'
+    login_inputs = []
+    logout_possible = True
+
+    def __init__(self,
+                 autocreate=False,  # create/update the user profile for the auth. user
+                 remove_blanks=False,  # Joe Doe -> JoeDoe
+                 coding = None,
+                ):
+        self.remove_blanks = remove_blanks
+        self.autocreate = autocreate
+        self.coding = coding
+
+    def logout(self, request, user_obj, **kw):
+        if self.name and user_obj and user_obj.auth_method == self.name:
+            url = request.url_root + u"../mellon/logout?ReturnTo=https%3A%2F%2Fwww.auf.org"
+            request.http_redirect(url)
+
+            user_obj.valid = False
+
+        return user_obj, True
+
+    def login(self, request, user_obj, **kw):
+        return ContinueLogin(user_obj)
+
+    def login_hint(self, request):
+        cur_url = request.url_root + request.path
+        return """
+<p style="display: inline-block;
+    vertical-align: middle;
+    text-align: right">
+
+<a
+ href="/mellon/login?ReturnTo=%s"
+ onmouseover="document.idauf_bouton.src='/idauf_bouton_survol.png';"
+ onmouseout="document.idauf_bouton.src='/idauf_bouton.png';"><img
+ id="idauf_bouton"
+ width="200"
+ height="32"
+ src="/idauf_bouton.png"></a>
+
+</p>""" % urllib.quote_plus(cur_url.encode('utf-8'))
+
+
+    def decode_username(self, name):
+        """ decode the name we got from the environment var to unicode """
+        if isinstance(name, str):
+            if self.coding:
+                name = name.decode(self.coding)
+            else:
+                # XXX we have no idea about REMOTE_USER encoding, please help if
+                # you know how to do that cleanly
+                name = wikiutil.decodeUnknownInput(name)
+        return name
+
+    def transform_username(self, name):
+        """ transform the name we got (unicode in, unicode out)
+
+            Note: if you need something more special, you could create your own
+                  auth class, inherit from this class and overwrite this function.
+        """
+        assert isinstance(name, unicode)
+        name = u''.join([c for c in name if c.isalpha()])
+
+        return name
+
+
+    def request(self, request, user_obj, **kw):
+        u = None
+        _ = request.getText
+        # always revalidate auth
+        if user_obj and user_obj.auth_method == self.name:
+            user_obj = None
+        # something else authenticated before us
+        if user_obj:
+            logging.debug("already authenticated, doing nothing")
+            return user_obj, True
+
+        auth_first_name = request.environ.get("MELLON_gn")
+        auth_last_name = request.environ.get("MELLON_sn")
+        auth_email = request.environ.get("MELLON_mail")
+
+        logging.debug("auth_fist_name = %r" % auth_first_name)
+        logging.debug("auth_last_name = %r" % auth_last_name)
+        logging.debug("auth_email = %r" % auth_email)
+        if auth_first_name and auth_last_name and auth_email:
+            auth_first_name = self.decode_username(auth_first_name)
+            auth_last_name = self.decode_username(auth_last_name)
+            auth_email = self.decode_username(auth_email)
+
+            auth_first_name = self.transform_username(auth_first_name)
+            auth_last_name = self.transform_username(auth_last_name)
+
+            auth_username = u"".join([auth_first_name, auth_last_name])
+
+            u = get_by_email_address(request, auth_email)
+            if not u:
+                u = user.User(request, auth_username=auth_username,
+                          auth_method=self.name, auth_attribs=('name', 'password', 'email', 'auth_method'))
+                u.email = auth_email
+                u.auth_method = self.name
+            else:
+                u.auth_method = self.name
+
+        logging.debug("u: %r" % u)
+        if u and self.autocreate:
+            logging.debug("autocreating user")
+            u.create_or_update()
+        if u and u.valid:
+            logging.debug("returning valid user %r" % u)
+            return u, True # True to get other methods called, too
+        else:
+            logging.debug("returning %r" % user_obj)
+            return user_obj, True
+#####################################################################FIXME
+
+
 # now we subclass that config (inherit from it) and change what's different:
 class Config(FarmConfig):
 
@@ -124,3 +266,6 @@
      </License></rdf:RDF> -->
      Site propuls&eacute; par <a href="http://moinmo.in/">MoinMoin</a>.
      '''
+    # Utiliser auth. mixte (moin + mellon).
+    from MoinMoin.auth import MoinAuth
+    auth = [MoinAuth(), MellonAuth(autocreate=True, remove_blanks=True)]

Configuration ID AUF en utilisant https://redmine.auf.org/projects/auth/wiki/MiseEnPlaceSP :

cd
mkdir ssl
cd ssl/
openssl req -new -x509 -keyout key.pem -out cert.pem -nodes -days 3650 -newkey rsa:2048 -subj "/CN=wiki.auf.org"
chmod 0600 key.pem
chmod 0644 cert.pem
chown root:root key.pem cert.pem
mv key.pem /etc/ssl/private/saml-wiki.auf.org-key.pem
mv cert.pem /etc/ssl/certs/saml-wiki.auf.org-cert.pem
wget --no-check-certificate https://id.auf.org/idp/saml2/metadata -O- | tee -a /etc/ssl/saml-id.auf.org-metadata.xml

Installation du mod mellon :

apt-get install libapache2-mod-auth-mellon

Configuration Apache + Mellon :

cd /etc/apache2/sites-available/
mv ~/moin-migration/wiki.auf.org-ssl.patch .
patch wiki.auf.org-ssl < wiki.auf.org-ssl.patch && rm wiki.auf.org-ssl.patch

Contenu pour wiki.auf.org-ssl.patch :

--- wiki.auf.org-ssl.orig       2015-02-18 12:14:20.000000000 -0500
+++ wiki.auf.org-ssl            2015-02-18 15:05:33.000000000 -0500
@@ -62,4 +62,33 @@
         SSLCertificateKeyFile /etc/ssl/private/_.auf.org-key.pem
         SSLCACertificateFile /etc/ssl/certs/GandiStandardSSLCA.pem
         SSLVerifyClient None
+
+    <Location />
+        AuthType "Mellon"
+        # si on veut imposer l'authentification avant d'accéder au site (100% privé)
+        #MellonEnable "auth"
+        # si on veut laisser le site web déclencher l'authentification (public + privé)
+        MellonEnable "info"
+
+        # les méta-données
+                MellonDefaultLoginPath "/"
+        MellonOrganizationName "wiki.auf.org"
+        MellonOrganizationDisplayName "fr" "Wiki AUF"
+        MellonOrganizationURL "http://www.auf.org"
+        MellonSPPrivateKeyFile /etc/ssl/private/saml-wiki.auf.org-key.pem
+        MellonSPCertFile /etc/ssl/certs/saml-wiki.auf.org-cert.pem
+        MellonIdPMetadataFile /etc/ssl/saml-id.auf.org-metadata.xml
+
+        # les conditions d'accès
+        MellonUser "mail"
+        MellonCond "mail" "^[^@]*@auf\.org$" [REG]
+        #MellonCond "mail" "jean-christophe.andre@auf.org" [OR]
+        #MellonCond "mail" "moussa.nombre@auf.org"
+        #MellonCond "eduPersonAffiliation" "employee"
+    </Location>
+
+    <Location /mellon/>
+        AuthType "Mellon"
+        MellonEnable "info"
+    </Location>
 </VirtualHost>

Activer le module :

a2enmod auth_mellon
service apache2 restart

TEST

NOTE

Si un employé AUF arrive pour la première fois par ID AuF, la compté sera crée dans le wiki sans permission pour modifier les pages wiki ou faire nouvelles pages.