Introduction

It's been 7 years since I have installed and used everyday the i3 tile window manager. I have never used something else and it proved to be a good choice. I can now focus on keyboard commands and I don't have to handle windows positions on the screen anymore.

Whenever I am forced to use another old fashioned hand positionning window manager, I fulminate against it. I am just waisting my time trying to focus on the program I need to use.

So far I have been very satisfied about my i3 usage. I just wrote a configuration file years ago and I never had to look at it. I just copy it to any new desktop computer that I own. It is a very stable window manager.

But last month, I found an alternative to i3 and I want to tell you how I use it as a replacement of i3. It is called sway and it aims to become an i3 replacement on the wayland graphical stack.

It's been years since everybody is using the Xorg graphical stack under GNU/Linux systems. It is very old as it predates the micro-computers era of the 80's. While being improved one small feet at a time, Xorg architecture has some drawbacks, inheritated from its beginnings.

Wayland has emerged a couple of years ago in order to completely get rid of the old Xorg stack principles. As an abstract, I can say that Wayland is the future of GNU/Linux desktop systems! For more information about the differences between Wayland and X, read this page.

Sway is a tiling window manager that works under Wayland. It aims to mimic i3, in its usage and even in it's configuration file. You just have to stick it into the right directory (~/.config/sway/config) and voila. Sway is coded in C and it is very efficient, compact and fast. Even if it hasn't reach version 1.0, my tests have shown that it is perfectly usable everyday.

I have use it for a month at home, on my laptop and even on my office job workstation and it just does work.

How to install Sway under Debian?

First things first, you need to be under Debian Buster because compiling sway from sources requires some packages that do not exist in Debian Stretch (like meson).

Debian Packages Dependencies

# apt install libgles2-mesa-dev libdrm2 libdrm-dev libegl1-mesa-dev xwayland\
  libgbm-dev libinput-dev libsystemd-dev libcap-dev libxcb-composite0-dev \
  libxcb-image0-dev libxcb-icccm4-dev libxcb-xkb-dev libpam0g-dev

Manual Dependencies

json-c

Unfortunately, json-c isn't in the required version, even on Debian Buster. We need to compile it by hand:

$ git clone https://github.com/json-c/json-c.git
$ cd json-c
$ sh autogen.sh
$ ./configure --prefix=/usr/local
$ make
# make install

wlroots

wlroot is a generic library for Wayland compositors. It has been developed focusing primarily Sway but it can also be used with other projects.

$ git clone https://github.com/swaywm/wlroots.git
$ cd wlroots
$ meson build
$ ninja -C build
# ninja -C build install

Sway building

Now it is time to build Sway.

$ git clone https://github.com/swaywm/sway.git
$ cd sway
$ meson build
$ ninja -C build
# ninja -C build install

Configuring Sway

You just need to copy your i3 configuration file into ~/.config/sway/config. Here is mine as an example with some adjustments for multiscreen and input configuration:

# Sway config file

# Keyboard configuration
input "5426:267:Razer_Razer_Arctosa" {
  xkb_layout fr
  xkb_variant latin9
  xkb_model pC105
  xkb_numlock enabled
}

# Dual screen configuration
output DP-1 pos 0 0 mode 1920x1080 background /usr/local/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png center
output DVI-I-2 pos 1920 0 mode 1680x1050 background /usr/local/share/backgrounds/sway/Sway_Wallpaper_Blue_1366x768.png center

set $mod Mod4

# Set font for lower bar
font pango:DejaVu Sans Mono 10

# Use Mouse+$mod to drag floating windows to their wanted position
floating_modifier $mod

# Start a terminal. I use terminology, the enlightenment terminal.
# It does work natively under Wayland.
# See https://www.enlightenment.org/about-terminology
bindsym $mod+Return exec terminology -B

# Lock the screen
bindsym $mod+m exec swaylock

# kill focused window
bindsym $mod+Shift+Q kill

# start dmenu (a program launcher)
bindsym $mod+d exec dmenu_run

# change focus
bindsym $mod+j focus left
bindsym $mod+k focus down
bindsym $mod+i focus up
bindsym $mod+l focus right

# alternatively, you can use the cursor keys:
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right

# move focused window
#bindsym $mod+Shift+J move left
#bindsym $mod+Shift+K move down
#bindsym $mod+Shift+L move up
#bindsym $mod+Shift+M move right

# alternatively, you can use the cursor keys:
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right

# split in horizontal orientation
bindsym $mod+h split h

# split in vertical orientation
bindsym $mod+v split v

# enter fullscreen mode for the focused container
bindsym $mod+f fullscreen

# change container layout (stacked, tabbed, default)
bindsym $mod+s layout stacking
bindsym $mod+z layout tabbed
bindsym $mod+e layout default

# change screen
bindsym $mod+x move container to output DVI-I-2
bindsym $mod+w move container to output DP-1

# toggle tiling / floating
bindsym $mod+Shift+space floating toggle

# change focus between tiling / floating windows
bindsym $mod+space focus mode_toggle

# focus the parent container
bindsym $mod+q focus parent

# focus the child container
#bindcode $mod+d focus child

# workspaces definition
workspace 1: Mail output DVI-I-2
workspace 2: Web output DP-1
workspace 3: Terminal output DP-1
workspace 4: Emacs output DP-1
workspace 5: Music output DVI-I-2

# switch to workspace
bindsym $mod+ampersand workspace 1: Mail
bindsym $mod+eacute workspace 2: Web
bindsym $mod+quotedbl workspace 3: Terminal
bindsym $mod+apostrophe workspace 4: Emacs
bindsym $mod+parenleft workspace 5: Music
bindsym $mod+minus workspace 6
bindsym $mod+egrave workspace 7
bindsym $mod+underscore workspace 8
bindsym $mod+ccedilla workspace 9
bindsym $mod+agrave workspace 10

# move focused container to workspace
bindsym $mod+Shift+ampersand move workspace 1: Mail
bindsym $mod+Shift+eacute move workspace 2: Web
bindsym $mod+Shift+quotedbl move workspace 3: Terminal
bindsym $mod+Shift+apostrophe move workspace 4: Emacs
bindsym $mod+Shift+parenleft move workspace 5: Music
bindsym $mod+Shift+minus move workspace 6
bindsym $mod+Shift+egrave move workspace 7
bindsym $mod+Shift+underscore move workspace 8
bindsym $mod+Shift+ccedilla move workspace 9
bindsym $mod+Shift+agrave move workspace 10

# reload the configuration file
bindsym $mod+Shift+C reload
# restart sway inplace (preserves your layout/session, can be used to upgrade sway)
bindsym $mod+Shift+R restart
# exit sway (logs you out of your X session)
bindsym $mod+Shift+E exit

# resize window (you can also use the mouse for that)
mode "resize" {
  # These bindings trigger as soon as you enter the resize mode
  # They resize the border in the direction you pressed, e.g.
  # when pressing left, the window is resized so that it has
  # more space on its left

  bindsym j resize shrink left 10 px or 10 ppt
  bindsym Shift+J resize grow   left 10 px or 10 ppt

  bindsym k resize shrink down 10 px or 10 ppt
  bindsym Shift+K resize grow   down 10 px or 10 ppt

  bindsym l resize shrink up 10 px or 10 ppt
  bindsym Shift+L resize grow   up 10 px or 10 ppt

  bindsym m resize shrink right 10 px or 10 ppt
  bindsym Shift+M resize grow   right 10 px or 10 ppt

  # same bindings, but for the arrow keys
  bindsym Left resize shrink left 10 px or 10 ppt
  bindsym Shift+Left resize grow   left 10 px or 10 ppt

  bindsym Down resize shrink down 10 px or 10 ppt
  bindsym Shift+Down resize grow   down 10 px or 10 ppt

  bindsym Up resize shrink up 10 px or 10 ppt
  bindsym Shift+Up resize grow   up 10 px or 10 ppt

  bindsym Right resize shrink right 10 px or 10 ppt
  bindsym Shift+Right resize grow   right 10 px or 10 ppt

  # back to normal: Enter or Escape
  bindsym Return mode "default"
  bindsym Escape mode "default"
  bindsym $mod+r mode "resize"
}

# lower bar configuration
bar {
    status_command i3status
    output DP-1
}

bar {
    output DVI-I-2
    status_command i3status
}

# assign workspaces
assign [title="mutt"] 1: Mail
assign [class="Firefox"] 2: Web
assign [title="Terminal" title="Terminal" app_id="terminology"] 3: Terminal
assign [title="Emacs"] 4: Emacs
assign [title="Cantata"] 5: Music

# Start my main tools when the session opens
exec terminology -B -T=mutt -n=Mutt -r=Mutt -e mutt
exec terminology -B -T=Terminal -n=Terminal -r=Terminal
exec terminology -B -T=Emacs -n=Emacs -r=Emacs -e emacs
exec cantata
exec firefox

Launch a sway session

Sway doesn't have a session manager. As Sway is a Wayland compositor it requires to be started whenever you start a session. For the moment, I have just modified my .bashrc configuration to start sway whenever I am login under tty1 and then configure the different graphical libraries (GTK/QT/EFL/etc.) to use Wayland instead of Xorg:

...
# Sway configuration
export LD_LIBRARY_PATH="/usr/local/lib"
# you can also configure your keyboard this way
#export XKB_DEFAULT_LAYOUT=fr
#export XKB_DEFAULT_VARIANT=latin9
#export XKB_DEFAULT_MODEL=pc105
export QT_QPA_PLATFORM=wayland
export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
export ELM_DISPLAY=wl
export ECORE_EVAS_ENGINE=wayland_shm

# Launch Sway when logging under tty1
if [ $(tty) = "/dev/tty1" ]; then
   sway
   exit 0
fi

I have gotten rid of all the session managers on my system (no more slim nor gnome-session). I am prompted ot log under the text mode console. OldSchoolCool!

What doesn't work very well?

Even if Sway is working very well on three of my computers there are still some problems around.

On some computers I have lots of glitches with firefox. This is my main problem for the moment. Firefox can only be compiled under Xorg, there is nothing official for Wayland. So it relies on XWayland and for some graphical cards, it seems to have some problems.

The second problem I have faced is a keyboard problem. On my laptop I could not use the traditionnal keys for moving a window towards a screen (mod+shift+number of the screen). I had to.modify the comfiguration file to reflect the base (without shift pressed) character of the key (eg: aecute for 3 on a french keyboard).

I had also some problems with (proprietary) games that required a full Xorg session. But as long as I am able to play to Stardew Valley, it is not really a problem. Furthermore, I can log in tty2 and launch Xorg by hand (startx).

The last problem is probably the fact that I have to compile sway every week because it is not already available in Debian...

As long as you use Gnome softwares, you will enjoy the Wayland experience. Same thing for Qt5 (with the configuration above).

Conclusion

As a conclusion, Sway impressed me. It is a Wayland replacement for i3. There is nearly no new features. I am not lost nor do I need to learn something new. Furthermore it is coded in C, a language I really enjoy and which is able to build a complete tile window manager in a robust, compact and fast way. If you are an i3 enthousiast, you will enjoy Sway whenever you will migrate to Wayland.

Posted dim. 14 oct. 2018 17:25:30 Tags:

Introduction

Ah, le courrier électronique, son utilisation est simple et quasi-universelle mais il existe tellement d'options et de fonctionnalités à ajouter à ce monument d'Internet qu'on oublie à quel point que faire fonctionner une plate-forme de courrier électronique requière de sérieuses compétences.

Aujourd'hui, nous allons mettre en place une technologie de filtrage au niveau du serveur pour filtrer les courriers en amont, en fonction des besoins de chaque utilisateur. Mission pas facile mais que nous allons néanmoins relever grâce à la technologie Sieve.

Récapitulatif de ce qu'il faut mettre en place

Exim4 propose la gestion de Sieve mais à un niveau assez bas: un fichier de filtre doit être déposé dans le répertoire de l'utilisateur pour qu'Exim le gère correctement. Mais, je pense que cette fonctionnalité n'est pas assez user-friendly.

On peut également implémenter Sieve du côté du serveur IMAP mais cela implique d'utiliser un service de délivrance de courrier et que ce service soit assuré par le serveur IMAP lui même. Dans le monde du courrier électronique, il existe deux grands types de service de délivrance de courrier "IMAP": LDA et LMTP. Nous retiendrons LMTP qui est plus "moderne" et surtout mieux implémenté dans Dovecot que LDA (qui repose sur un binaire externe).

Bien entendu, il faut dire au MTA qu'il doit utiliser ce service LMTP, il faudra donc modifier la configuration d'Exim4.

Une fois LMTP activé, on pourra mettre en place la gestion de Sieve dans Dovecot. Néanmoins, le problème sera identique à celui d'Exim: il reste à fabriquer les fichiers de filtres et à les déposer sur le serveur...

Heureusement, il existe un service dédiéà ça: ManageSieve. Il en existe une implémentation dans Dovecot que nous allons installer et configurer.

Enfin, si on souhaite que les filtres soient personnalisés, il reste à offrir une interface permettant de les déposer depuis le Webmail. C'est ce qui est permis par l'extensions ManageSieve de Roundcube et que nous allons également mettre en place.

On le voit, il y a du boulot en perspective... Commençons dès à présent et pas à pas !

Installation de LMTP pour Dovecot

Avant de commencer, il nous faut un serveur LMTP. Il existe une extension Dovecot qui fait très bien ce travail.

Installation

Sous Debian, c'est assez simple:

# apt install dovecot-lmtpd

Le paquet fait moins d'1Mo, pas de problème sur un PlugComputer.

Configuration

Pour configurer correctement ce mode de transport du courrier électronique, il ne faut pas oublier quelle est notre cible. En effet, nous voulons qu'Exim utilise le service LMTP pour transmettre les courriers électroniques qui seront ensuite gérés par Dovecot, lequel appliquera alors les filtres Sieve.

L'activation du protocole LMTP se fait dans le fichier maître de configuration, à savoir /etc/dovecot/conf.d/10-master.conf:

# Configuration du service LMTP
service lmtp {
  # On active le protocole LMTP sur une socket UNIX
  unix_listener lmtp {
    #mode = 0666
  }

  # On désactive le protocole LMTP par TCP
  #inet_listener lmtp {
    # Avoid making LMTP visible for the entire internet
    #address =
    #port = 
  #}
  # On va réserver 2 processus pour LMTP
  process_min_avail = 2

  # On veut que LMTP loggue les erreurs
  executable = lmtp -L
}

La configuration fine du protocole LMTP se fait dans le fichier /etc/dovecot/conf.d/20-ltmtp.conf:

##
## Configuration LMTP
##

# Pas de proxy LMTP
lmtp_proxy = no

# Pour les alias délimités, on va poser les courriels dans la 
# boîte finale et non dans la boîte aliasée.
lmtp_save_to_detail_mailbox = no

# Pas de vérification de quota
lmtp_rcpt_check_quota = no

# Toujours écrire dans la boîte aux lettres finale
# et non dans la boîte aliasée.
lmtp_hdr_delivery_address = final

protocol lmtp {
  # Les extensions gérées par lmtp
  mail_plugins = $mail_plugins
  # Le fichier de log spécifique
  info_log_path = /var/log/dovecot/dovecot-lmtp.log
  # Il faut enlever la partie du domaine pour nommer nos utilisateurs
  auth_username_format = %n
}

Intégration de LMTP dans Exim4

Maintenant que nous disposons d'un service LMTP, il reste à le faire utiliser par Exim. Par défaut, au moins, dans ma configuration simple d'Exim, j'utilise un mode de délivrance de courrier assez basique: Exim pose le message sous forme de fichier dans une arborescence Maildir. Il s'agit du transport maldir_home.

Pour mettre en place LMTP dans Exim, vous devrez configurer un router dédié ainsi qu'un transport vers le service. Nous allons placer ce transport dans le fichier /etc/exim4/conf.d/tranport/30_exim4-config_dovecot_lmtp:

dovecot_lmtp:
        driver = lmtp
        socket = /var/run/dovecot/lmtp
        #maximum number of deliveries per batch, default 1
        batch_max = 200
        # on supprime les suffixes/préfixes
        rcpt_include_affixes = false

Il reste ensuite à utiliser ce transport. Le moyen le plus simple consiste à utiliser le fichier de macros fourni par Debian: /etc/exim4/update-exim4.conf.conf et de modifier la variable dc_localdelivery qui permet d'indiquer le transport servant à la délivrance locale des courriels. Donc mon cas, j'ai juste modifié la valeur à :

dc_localdelivery='dovecot_lmtp'

Ensuite, vous pouvez redémarrer Exim (via systemctl bien-sûr) et faire un test d'adresse (via l'option -bt) pour lire le transport qui sera utilisé.

Mise en place de Sieve dans Dovecot

Installation

Ok, LMTP est en place et fonctionnel, il nous reste à nous occuper de la configuration de Sieve dans Dovecot. Il faut juste installer le paquet dovecot-sieve et son pendant administratif dovecot-managesieved:

# apt install dovecot-sieve dovecot-managesieved

Configuration

La configuration est assez simple. Il faut juste activer le module dans le transport adapté (ce sera LMTP pour nous) et configurer le fichier de l'extension.

Vous devrez d'abord activer le module sieve de LMTP. L'action se trouve dans la conf de LMTP, /etc/dovecot/conf.d/20-lmtp.conf:

protocol lmtp {                                                                                                                                             
  mail_plugins = $mail_plugins sieve                                                                                                                        
  ...
}

Ensuite, l'action se déroule dans /etc/dovecot/conf.d/90-sieve.conf. Je dirais que la configuration par défaut fait très bien le job dans la majorité des cas. La ligne la plus importante étant sans doute celle qui indique l'emplacement du répertoire de filtre et le fichier par défaut:

sieve = file:~/sieve;active=~/.dovecot.sieve

Cette ligne indique que le répertoire des filtres sieve sera ~/sieve et que le filtre par défaut à utiliser sera le lien symbolique ~/.dovecot.sieve.

A ce stade, la configuration est totalement compatible avec celle de l'interface ManageSieve de Roundcube donc, pour 90% des cas, ça ne sert à rien d'aller plus loin.

Pour plus d'informations, je vous invite à lire la page de référence.

Mise en place de ManageSieve dans Dovecot

Il reste maintenant à configurer ManageSieve dans Dovecot. Nous souhaitons activer le service uniquement sur localhost car l'accès à la configuration se fera via Roundcube qui est sur la même machine, donc pas besoin de présenter un port sur une IP publique.

Vous devez simplement renseigner le fichier de configuration /etc/dovecot/conf.d/20-managesieve.conf avec le contenu suivant:

##                                                                                 
## Configuration ManageSieve pour Dovecot                                          
##                                                                                 

# Nous activons ManageSieve                                                        
protocols = $protocols sieve

# Configuration de la connection au service                                        
service managesieve-login {
  inet_listener sieve {
    address = ::1, 127.0.0.1
    port = 4190
  }

  #inet_listener sieve_deprecated {                                                
  #  port = 2000                                                                   
  #}                                                                               

  # Number of connections to handle before starting a new
  process. Typically       
  # the only useful values are 0 (unlimited) or 1. 1 is more secure,
  but 0         
  # is faster. <doc/wiki/LoginProcess.txt>                                         
  #service_count = 1                                                               

  # Number of processes to always keep waiting for more connections.               
  #process_min_avail = 0                                                           

  # If you set service_count=0, you probably need to grow this.                    
  #vsz_limit = 64M                                                                 
}

#service managesieve {                                                             
  # Max. number of ManageSieve processes (connections)                             
  #process_limit = 1024                                                            
#}                                                                                 

# Service configuration                                                            

protocol sieve {
  # Maximum ManageSieve command line length in bytes. ManageSieve
  usually does     
  # not involve overly long command lines, so this setting will not
  normally       
  # need adjustment                                                                
  #managesieve_max_line_length = 65536                                             

  # Maximum number of ManageSieve connections allowed for a user from
  each IP      
  # address.                                                                       
  # NOTE: The username is compared case-sensitively.                               
  #mail_max_userip_connections = 10

  # Space separated list of plugins to load (none known to be useful
  so far).      
  # Do NOT try to load IMAP plugins here.                                          
  #mail_plugins =                                                                  

  # MANAGESIEVE logout format string:                                              
  #  %i - total number of bytes read from client                                   
  #  %o - total number of bytes sent to client                                     
  #managesieve_logout_format = bytes=%i/%o                                         

  # To fool ManageSieve clients that are focused on CMU's timesieved
  you can       
  # specify the IMPLEMENTATION capability that Dovecot reports to
  clients.         
  # For example: 'Cyrus timsieved v2.2.13'                                         
  #managesieve_implementation_string = Dovecot Pigeonhole                          

  # Explicitly specify the SIEVE and NOTIFY capability reported by the
  server      
  # before login. If left unassigned these will be reported
  dynamically            
  # according to what the Sieve interpreter supports by default (after
  login       
  # this may differ depending on the user).                                        
  #managesieve_sieve_capability =                                                  
  #managesieve_notify_capability =                                                 

  # The maximum number of compile errors that are returned to the
  client upon      
  # script upload or script verification.                                          
  #managesieve_max_compile_errors = 5                                              

  # Refer to 90-sieve.conf for script quota configuration and
  configuration of     
  # Sieve execution limits.                                                        
}

Mise en place de ManageSieve dans Roundcube

Maintenant que nous avons configuré l'infrastructure de bas niveau, il reste à configurer Roundcube. Ce dernier propose une extension bien nommée puisqu'elle s'appelle ManageSieve.

Installation

Vous devez vous assurer que vous disposez du paquet roundcube-plugins pour disposer de cette fonctionnalité:

# apt install roundcube-plugins

Mise en oeuvre

Vous devez activer l'extension en vous assurant qu'elle soit dans les extensions autorisées de Roundcube. Pour cela, allez modifier le fichier /etc/roundcube/config.inc.php:

// List of active plugins (in plugins/ directory)                                  
$config['plugins'] = array(
'archive',
'calendar',
'carddav',
'emoticons',
'managesieve',
'zipdownload',
'enigma'
);

Il reste ensuite à paramétrer finement l'extension. On peut le faire en ajoutant le fichier /etc/roundcube/plugins/managesieve/config.inc.php avec le contenu suivant:

<?php
// Le port managesieve utilisé. Ce sera 4190, le port réservé.                     
$config['managesieve_port'] = 4190;

// L'emplacement du serveur. Dans notre configuration, ce sera                     
// localhost car Roundcube est sur la même bécane.                                 
$config['managesieve_host'] = 'localhost';

// Méthode d'authentification utilisée.                                            
// Nous n'en employons aucune car nous sommes sur la même bécane.                  
$config['managesieve_auth_type'] = null;

// Option pour utiliser un compte alternatif pour
l\'authentification.             
// Ici, nous n'utilisons pas cette option.                                         
$config['managesieve_auth_cid'] = null;
$config['managesieve_auth_pw'] = null;

// On s'en fout d'utiliser TLS pour se connecter.                                  
$config['managesieve_usetls'] = false;
$config['managesieve_conn_options'] = null;

// default contents of filters script (eg. default spam filter)                    
$config['managesieve_default'] = '/etc/dovecot/sieve/global';

// Nom du script utilisé lorsque l'utilisateur n'a rien configuré.                 
$config['managesieve_script_name'] = 'managesieve';

// On est en 2018, UTF-8 est partout !                                             
$config['managesieve_mbox_encoding'] = 'UTF-8';

// Option pour Dovecot.                                                            
$config['managesieve_replace_delimiter'] = '';

// Ici, on peut désactiver des plugins Sieve.                                      
// Ce ne sera pas le cas sur notre configuration.                                  
$config['managesieve_disabled_extensions'] = array();

// Nous ne sommes pas en mode Debug.                                               
$config['managesieve_debug'] = false;

// Nous désactivons les options spécifiques de Kolab.                              
$config['managesieve_kolab_master'] = false;

// Extension des fichiers Sieve. Ce sera .sieve pour se conformer à                
// Dovecot.                                                                        
$config['managesieve_filename_extension'] = '.sieve';

// Une liste de noms de scripts Sieve non présentés à l\'utilisateur.
// Dans notre cas, nous n'en avons aucun.                                          
$config['managesieve_filename_exceptions'] = array();

// Une liste de domaine fermée pour contraindre les redirections.                  
// Vers d'autres domaines de courriel.                                             
$config['managesieve_domains'] = array();

// Options pour la gestion des absences.                                           
// Nous activons l'interface de gestion d'absences.                                
$config['managesieve_vacation'] = 1;

// Durée par défaut de l'absence en jours.                                         
$config['managesieve_vacation_interval'] = 7;

// Pré-remplissage de l'adresse utilisée pour la réponse.                          
$config['managesieve_vacation_addresses_init'] = true;

// Méthodes utilisées pour renvoyer le message d'absence.                          
$config['managesieve_notify_methods'] = array('mailto');
?>

Un exemple de filtre

Ce script permet de détecter ce qui vient d'une mailing-list et de le balancer dans une boîte dédiée.

# rule:[QGIS developper mailing list]                                                                                                                       
if anyof (header :contains "from" "qgis-developer@lists.osgeo.org", header :contains "return-path" "qgis-developer@lists.osgeo.org")
{                                                                                                                                
        fileinto "QGis-dev";
}

Mais, le plus simple est d'utiliser l'interface de Rouncube, c'est plus user-friendly !

Conclusions

Bon, c'était un poil complexe quand même ! Il y en a de partout et nous avons bien travaillé quand même. Faisons le bilan:

  • Nous avons modifié la configuration du MTA (Exim4) pour lui faire utiliser un transport dédié.
  • Nous avons mis en place un service LMTP via Dovecot.
  • Nous avons intégré et configuré la gestion de Sieve dans Dovecot.
  • Nous avons intégré et configuré un service ManageSieve via Dovecot.
  • Nous avons installé une extension de Rouncube permettant à l'utilisateur final de gérer ses propres scripts.

Pas simple effectivement pour une fonctionnalité qui peut sembler assez basique. Mais c'est ainsi: le courrier électronique applique à fond le principe UNIX: une fonctionnalité = un outil dédié. C'est comme ça et ça démontre qu'il sera toujours complexe d'administrer une plate-forme de courrier électronique. Le niveau de compétences à avoir est quasi identique pour une plate-forme mono-utilisateur que pour une plate-forme d'entreprise.

Voilà de quoi ajouter à votre CV qui ne pourra que satisfaire vos futurs recruteurs...

Posted dim. 14 janv. 2018 20:25:35 Tags:

Introduction

Dans la lutte contre le SPAM, j'ai déjà adopté certaines mesures comme le greylisting. C'est efficace même si cela n'est pas parfait. Néanmoins, il y a un élément dont je ne dispose toujours pas. En effet, je ne sais pas qui est le vendu de l'histoire...

Car régulièrement, au gré de ma vie numérique connectée, je dois laisser trainer mon adresse de courrier électronique. Bien entendu, même si les sites qui récupèrent cette information s'engagent tous à ne pas la refourguer à d'autres compagnons, mon niveau de confiance est proche de l'ensemble vide. Mais alors, que faire ?

Les alias délimités viennent à notre rescousse

Un moyen simple consiste à utiliser ce que j'appelle des alias délimités. C'est sans doute une mauvaise traduction de l'option 'recipient delimiter' du MTA Postfix. Cela consiste en l'utilisation d'un caractère de délimitation au sein d'une adresse de courrier électronique.

Concrètement, cela prend la forme suivante: si vous avez une adresse de courrier en toto@mondomaine.example, vous pouvez utilisez aussi une adresse du type toto_cequevousvoulez@mondomaine.example. Elle sera acceptée par votre MTA et le message sera routé vers toto@mondomaine.example.

L'astuce consiste à utiliser un délimiteur (ici, c'est '' mais ça peut être ce qu'on veut) en suffixe d'une adresse autorisée, c'est-à-dire qui existe réellement sur votre serveur. Ainsi, lorsque vous confiez votre adresse à un site marchand qui en a vraiment besoin, vous pouvez simplement utiliser totonomdumarchand@mondomaine.example comme adresse. Elle sera reconnue par votre MTA et vous recevrez du courrier électronique directement à votre adresse principale, sans aucune configuration.

L'intérêt de cette méthode consiste à fournir uniquement des adresses personnalisées pour chaque site sur lequel vous avez un compte. De cette manière, si vous récupérez du spam, il vous suffit d'afficher l'adresse d'origine (elle est présente dans les en-têtes et nombreux sont les MUA qui l'affichent (souvent pas par défaut).

Ainsi, vous saurez quel site a proprement revendu ou refourgué votre précieuse adresse. Google implémente cette astuce avec le délimiteur '+'.

Après cet intermède de haut niveau, passons à la mise en oeuvre...

Quelques rappels sur la configuration d'Exim4 sous Debian

Bon, ce qui est bien avec Debian et aussi avec Exim, c'est qu'une fois que la configuration est correctement implémentée, on n'a plus à y toucher pendant de nombreuses années.

Concrètement, le vrai fichier de configuration utilisé par Exim est situé dans /var/lib/exim4/config.autogenerated. Ce fichier est, comme son nom l'indique, généré par un programme dédié nommé update-exim4.conf (oui, je sais, un exécutable avec un .conf dedans, c'est peu courant). Ce dernier utilise la configuration éclatée située dans /etc/exim4/conf.d ainsi que le fichier de macros /etc/exim4/update-exim4.conf.conf (ça fait beaucoup de .conf non ?).

Pour modifier la configuration d'Exim, vous devez donc modifier des choses dans les fichiers situés dans /etc/exim4/conf.d puis lancer update-exim4.conf et relancer votre service exim4 (systemctl restart exim4).

Implémentation des alias délimités dans Exim4

Je ne vais pas vous ré-expliquer les principes d'Exim, il me faudrait un livre entier. Vous pouvez néanmoins vous réferrer à la documentation officielle qui est pour le coup, complète.

Comme tout ce qui a trait à la délivrance de courrier électronique dans Exim, nous allons simplement créer un router spécifique qui se charge de vérifier la présence du délimiteur en suffixe, de l'enlever avec tout le reste de l'adresse initiale et de balancer le message vers un autre routeur, chargé lui des adresses "officielles".

Je vous invite à créer un fichier nommé /etc/exim4/conf.d/router/310_recipient_delimiter (le nom est important pour l'ordre d'enchaînement des routers) avec le contenu suivant:

### router/300_recipient_delimiter
##################################

# Ce router gère la redirection vers les adresses dynamiques, définies
# avec un délimiteur. ex: toto__whatever est redirigé vers toto

recipient_delimiter:
  debug_print = "R: recipient_delimiter for $local_part@$domain"
  driver = redirect
  domains = +local_domains
  local_part_suffix =  __* : ..*
  data =  ${quote_local_part:$local_part}@$domain
  redirect_router = system_aliases

Voici les quelques explications indispensables à la compréhension de ce que nous faisons.

D'abord, nous créons un router spécifique. Il est nommé recipient_delimiter. Vous pouvez mettre ce que vous voulez comme nom mais, pour rester conforme à ce qui existe dans la littérature des MTA, j'utilise le terme recipient delimiter.

debug_print est une instruction qui imprime un message lorsqu'on est dans le mode debug d'Exim (cf plus bas). Il affiche une chaîne de caractères qui nous permet de prendre connaissance des variables local_part et domain. Ces variables contiennent respectivement la partie initiale de l'adresse en cours de traitement (toto) et le domaine traité. Le fait de mettre $ devant un nom de variable permet d'afficher son contenu (c'est $ qui permet le développement du contenu de la variable).

driver = redirect indique que ce router est de type redirect. C'est le router d'Exim qui permet la redirection de message vers d'autres routers. C'est pleinement ce que nous cherchons à faire: rediriger toto__whatever vers toto qui sera gérée par un autre router (system_aliases dans notre cas).

domains est la liste des domaines acceptés par ce router. Dans notre cas, il s'agit des domaines du système, stocké dans la variable local_domains. En fait cette variable est une liste nommée, on utilise le caractère + pour indiquer qu'on souhaite utiliser le contenu de la liste et non la chaîne de caractères en direct.

local_part_suffix est une condition pour que le router capture le message. Concrètement, si le contenu de cette condition est vérifié, alors le message est géré par notre router recipient_delimiter. Si ce n'est pas le cas, alors le message n'est pas traité par ce router (et il y a de fortes chances pour qu'à la fin, il soit rejeté). La chaîne de correspondance utilise la syntaxe d'Exim des listes. Concrètement, le suffixe cherché est du type __* ou ..* qui traite donc les adresses du type toto__whatever ou toto..whatever (* correspond à n'importe quel caractère). Attention, cette option est plus puissante qu'on ne peut le penser. En effet, le simple fait de déclarer un suffixe de partie locale d'adresse suffit à réduire la partie locale de l'adresse à la partie avant le suffixe.

data est une option de configuration des routers de type redirect. Elle indique, dans la syntaxe Exim, un moyen de trouver l'adresse réelle (toto@mondomaine.example) à partir de l'adresse initiale (toto__whatever@mondomaine.example). quote_local_part est un opérateur qui permet de mettre entre quotes la partie locale de l'adresse. Il faut l'utiliser chaque fois qu'on travaille sur la partie locale de l'adresse. Il permet de se conformer à la RFC 2822 qui gère la syntaxe du courrier électronique. On utilise ici local_part directement car local_part_suffix a déjà fait le travail de séparation pour nous.

Enfin, redirect_router est une autre option des routers de type redirect qui permet d'indiquer vers quel autre router ou balance le message qui correspond au suffixe et qui contiendra l'adresse réelle trouvée. Dans notre cas, il s'agit de system_aliases qui gère les alias systèmes et qui est le router que j'utilise pour mes comptes de messagerie configurés. Ce dernier gère la suite comme un grand.

Attention, j'utilise un transport assez simple (celui qui distribue le courrier dans un répertoire utilisateur en direct) mais si vous utilisez un transport plus élaboré qui utilise un service externe, il faudra sans doute configurer le service externe pour prendre en compte aussi l'adresse originelle qui est transmise dans les en-tête du message.

Tester notre configuration

Après avoir appliqué votre configuration, vous pouvez la tester en utilisant l'option -bt du binaire exim, de la manière suivante:

# exim4 -bt toto__nimportequoi
R: recipient_delimiter for toto__nimportequoi@mondomaine.example
R: system_aliases for toto__nimportequoi@mondomaine.example
R: system_aliases for moi@mondomaine.example
R: userforward for moio@mondomaine.example
R: procmail for moi@mondomaine.example
R: maildrop for moi@mondomaine.example
R: lowuid_aliases for moi@mondomaine.example (UID 1053)
R: local_user for moi@mondomaine.example
moi@medspx.fr
    <-- toto@mondomaine.example
    <-- toto__nimportequoi@mondomaine.example
  router = local_user, transport = maildir_home

Ici, on voit que toto__nimportequoi est transformé en toto puis en moi (la véritable adresse car toto est aussi un alias mais non dymanique, déclaré dans /etc/aliases)

En cas de problème, vous aurez probablement un message du type:

R: system_aliases for toto__nimportequoi@mondomaine.example
toto__nimportequoi@mondomaine.example is undeliverable: Unrouteable address

Afficher la source dans Roundcube

Dans Roundcube, l'adresse originelle n'est pas affichée par défaut, vous devrez activer la colonne À pour l'afficher dans la liste des courriels entrants.

Conclusions

Avec ce routeur, vous avez une infinité d'adresses de courrier électronique à votre disposition pour lutter contre le SPAM en sachant qui vous a vendu.

Maintenant, cet article ne parle pas de la contre-offensive possible qui peut prendre une forme légale (si vous avez envie de prendre du temps pour ça), une redirection vers du SPAM par défaut de cette adresse une fois qu'elle a été revendue ou encore plus radical, un bannissement de l'adresse au niveau du serveur.

Références

Posted sam. 13 janv. 2018 17:37:07 Tags:

Introduction

L'installeur Debian (d-i pour les intimes) est le programme qui sert à installer le système d'exploitation GNU/Linux Debian sur une machine (physique ou virtuelle) à partir d'un support d'installation qui peut être un CD, une clef USB ou une image accessible sur un réseau IP. Si vous avez déjà installé manuellement Debian sur une machine vous avez déjà forcément utilisé ce logiciel qui permet de préconfigurer le système d'exploitation sur un grand nombre de points avant que celui-ci ne soit pleinement opérationnel à l'issue du processus.

L'installeur Debian vous offre une interface utilisateur pour règler les paramètres tels que la langue du système, le partitionnement des périphériques de masse, la configuration du réseau ainsi que de choisir quels sont les groupes de paquets qui seront installés en plus du système de base. Il suffit de répondre aux questions des différentes boîtes de dialogue pour obtenir un système bien paramétré.

Mais si vous devez déployer Debian sur une centaine de machines avec pour chacune d'entre elles une configuration adaptée, allez-vous vous taper cent fois les réponses manuelles dans l'installeur Debian ? Certains créeront des images pré-installées qui seront recopiées bits à bits sur le support de stockage (processus dit de "Ghost" de machine) mais cette tendance tend à diminuer.

Saviez-vous qu'il est possible d'installer un système d'exploitation GNU/Linux Debian avec une configuration personnalisée et ce de manière totalement automatisée ? Ce mécanisme porte le nom de "preseed" et il est disponible dans l'installeur Debian depuis de très nombreuses années.

Preseed, comment ça marche ?

Le principe du fichier preseed est de contenir les réponses posées en temps normal par l'installeur Debian. Celui-ci ouvre normalement tout un tas de boîtes de dialogues selon un scénario bien précis. L'intérêt du fichier preseed est de répondre à ces questions en amont. Si une boîte de dialogue dispose déjà d'une réponse, elle ne sera pas présentée à l'utilisateur. Si on travaille bien, on peut donc complètement automatiser l'installation du système sur la machine.

Le fichier preseed est un simple fichier texte qui contient des chaînes de configuration qui prennent la forme suivante:

d-i module/paramètre type_de_données contenu_de_la_réponse
  • d-i indique qu'on s'adresse à l'installeur Debian (d-i) ou un autre programme si ce dernier utilise debconf.
  • module indique quel est le module de l'installeur Debian concerné. Car l'installeur Debian fonctionne avec des modules. Par exemple un module s'occupe de la configuration réseau (netcfg), un autre du partionnement (partman), etc.
  • paramètre indique quelle est la variable qu'on souhaite pré-renseigner.
  • type_de_données indique quel est le type de la variable concernée (ex: string pour une chaîne de caractère, toggle pour cocher une case, etc.).
  • contenu_de_la_réponse contient la valeur affectée à la variable.

Ces chaînes reprennent la syntaxe Debconf pour ceux qui l'auraient remarqué.

Pour utiliser un fichier preseed, il existe plusieurs méthodes. La plus simple consiste à mettre dans l'initrd de l'image d'installation un fichier nommé preseed.cfg à la racine. Une autre méthode qui est du même niveau consiste à faire indiquer ce fichier par un serveur DHCP (en cas d'installation par le réseau). Ces techniques sont décrites dans la documentation officielle Debian et je vous invite à lire cette partie pour mieux comprendre.

Plus directement, vous pouvez utiliser l'astuce présentée ici pour inclure le fichier preseed dans l'initrd.

Voyons maintenant quelques astuces qui nous permettront de voir quels modules et quelles paramètres sont utilisés dans l'installeur Debian.

Astuce n°1: Bien configurer le clavier

Cette astuce est assez simple mais j'ai parfois eu du mal à trouver les bonnes commandes pour garantir d'avoir un clavier français (azerty) configuré au redémarrage de la machine suite à l'installation. Voici donc les chaînes de configuration:

### Localization
# Configurer la locale permet aussi de configurer
# la langue et le pays de l'OS
d-i debian-installer/locale string fr_FR.UTF-8

# Choix du clavier
# keymap est un alias de keyboard-configuration/xkb-keymap
d-i keymap select fr(latin9)
# On désactive la sélection fine de la configuration du clavier
d-i keyboard-configuration/toggle select No toggling

Astuce n°2: Désactiver la détection de réseau

Parfois, on ne souhaite pas que l'installeur fasse de la détection de réseau. C'est par exemple le cas lors d'un désastre majeur qui affecte une infrastructure et notamment son réseau. Il faut bien parfois rebâtir un serveur de base de l'infrastructure et ce, assez rapidement, sans que ce dernier ne puisse se connecter au réseau local. Cela peut également être intéressant pour remonter une machine de zéro sans le réseau.

La configuration de ce dernier peut d'ailleurs être ajoutée plus tard lors de l'installation d'un paquet de configuration ou par simple copie de fichier à l'issue du processus d'installation.

Pour y parvenir, voici les chaînes que j'utilise:

### Configuration Réseau
# On désactive la configuration réseau
d-i netcfg/enable boolean false

# Mais on doit quand même configurer le nom de machine
d-i netcfg/get_hostname string goofy
# Ainsi que le domaine
d-i netcfg/get_domain string example.com

# Ici, on définit le nom local de la machine
d-i netcfg/hostname string goofy
...
# On désactive l'utilisation de NTP pour configurer l'heure (le réseau n'est pas disponible)
d-i clock-setup/ntp boolean false

Astuce n°3: Partionnement automatique

Un des points complexes de d-i est la gestion du partionnement. En effet, on peut paramétrer totalement le programme partman de l'installeur Debian (le programme qui gère la configuration des partitions) via le fichier preseed.

Ici, nous allons aborder un point simple: on veut utiliser une table de partition au format GPT (on est en 2015 !) et tout mettre dans une seule partition.

### Partitionnement
# Nous voulons une table de partition au format GPT
d-i partman-basicfilesystems/choose_label string gpt
d-i partman-basicfilesystems/default_label string gpt
d-i partman-partitioning/choose_label string gpt
d-i partman-partitioning/default_label string gpt
d-i partman/choose_label string gpt
d-i partman/default_label string gpt
partman-partitioning partman-partitioning/choose_label select gpt

# Seul le premier disque est partionné
d-i partman-auto/disk string /dev/sda
# On partionne en "normal": pas de RAID ni de LVM
d-i partman-auto/method string regular
# Pour être sûr, on supprime une éventuelle configuration LVM
d-i partman-lvm/device_remove_lvm boolean true
# Même chose pour le RAID
d-i partman-md/device_remove_md boolean true
# Chaînes pour ne pas toucher la configuration LVM (donc pas de configuration)
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true

# L'installation sera simple: on fout tout dans une seule partition
# C'est ce que fait la recette atomic
d-i partman-auto/choose_recipe select atomic

# On valide sans confirmation utilisateur la configuration de partman
d-i partman-md/confirm boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true

# fstab utilisera des UUID plutôt que des noms de périphériques
d-i partman/mount_style select uuid

Pour un autre example, nous allons configurer un partitionnement un peu plus complexe:

  • Nous allons utiliser un disque dur complet (le premier)
  • Sur ce volume, nous allons réaliser 4 partitions (principalement en ext4):
    • 20 Go pour l'espace système.
    • 20 Go pour les répertoires home.
    • 60 Go pour le répertoire /opt.
    • 200% de la taille de la RAM et au maximum 16Go pour le swap.
d-i partman-auto/expert_recipe string                         \
      boot-root ::                                            \
              20480 20480 20480 ext4                          \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ / }                         \
              .                                               \
              20480 20480 20480 ext4                          \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ /home }                     \
              .                                               \
              60000 60000 60000 ext4                          \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ /opt }                      \
              .                                               \
              200% 16000 16000 linux-swap                     \
                      method{ swap } format{ }                \
              .

Pour appliquer cette recette, il faut bien entendu supprimer la recette atomic du point précédent.

Ce qu'il faut retenir de cette recette:

  • Tout doir tenir sur une seule ligne. C'est pourquoi on échappe tout.
  • Chaque description de partition se termine par un caractère ..
  • Les trois chiffres en entrée de partition correspondent à la taille minimale, la taille prioritaire et la taille maximum.
  • Les tailles peuvent s'exprimer également en pourcentage de la RAM.
  • method { format } indique qu'on souhaite formatter la partition.
  • format { } effectue le formattage.
  • use_filesystem { } indique qu'on souhaite utiliser cette partition dans notre futur système d'exploitation.
  • mountpoint { xxx } permet de préciser le point de montage de la partition.
  • la méthode method { swap } permet d'indiquer qu'on utilise un swap.

On peut bien sûr aller plus loin et créer des volumes RAID ou LVM et spécifier comment faire avec. Vous pouvez lire la documentation de l'installeur Debian sur ce sujet: partman-auto-recipe.txt et partman-auto-raid-recipe.txt.

Astuce n°4: Désinstaller des paquets non indispensables

Parfois, l'installation de base de Debian peut ne pas convenir. Par exemple, en ce qui concerne l'éditeur de texte par défaut. Ce dernier est vim.tiny ce qui ne correspond pas du tout à ce que j'installe de facto sur mes machines (je suis un sale emacs fanboy). On pourrait également avoir le même raisonnement avec le MTA (Exim4) qui pour certaines configuration peut paraître "overkill" (on peut le remplacer par un MTA plus léger comme msmtp par exemple).

Voici un exemple de suppression de paquets dans un fichier preseed:

## Suppression de certains paquets
d-i preseed/late_command string \
    in-target apt-get -y purge nano; \
    in-target apt-get -y purge vim-tiny; \
    in-target apt-get -y purge vim-common

Le principe est assez simple à comprendre: on lance une commande terminale qui va se charger de supprimer ces paquets via le classique apt-get. Cette commande est unique et c'est pour ça qu'on est obligé de mettre une seule ligne qu'on peut bien entendu "échapper". Dans le cas présent, le in-target indique qu'on joue la commande dans le système installé (et non dans l'environnement de l'installeur Debian).

Si vous avez bien compris le fonctionnement de l'installeur Debian, les paquets de la catégorie "essential" sont tous installés par défaut. Cela signifie que dans notre cas, l'installeur va commencer par installer tous ces paquets et qu'il les désinstallera lorsqu'il traitera la chaîne preseed/late_command. Ce n'est pas très élégant mais c'est comme ça que ça marche. Dans la pratique, on enlève quand même assez peu de paquets "essential".

Astuce n°5: Configurer mes dépots de paquets APT

Depuis l'avènement d'httpredir, ce point n'est pas forcément très intéressant mais si vous avez des dépôts Debian personnalisés vous serrez sans doute tenté de les incorporer directement via l'installeur Debian. Voici comment y parvenir...

Avant tout, sachez que c'est complexe et qu'on ne peut pas tout faire. Le premier point est de définir un mirroir Debian. Il semble que ce soit nécéssaire pour que l'installeur Debian ne pose pas de question sur ce sujet. Il existe un certain nombre de chaînes de configuration pour cela.

Ensuite, on indique qu'on ne souhaite pas utiliser de mirroir. La configuration pré-existante n'est donc pas injectée dans /etc/apt/sources.list. Dans un troisième temps, on indique qu'on souhaite activer les services security et updates. Les adresses de ces services sont hardcodées (security.debian.org). Enfin, on peut procéder à l'ajout de notre dépôt local avec une chaîne de configuration digne de ce nom. On peut en ajouter autant qu'on veut et même y glisser des commentaires.

### Paramètres de mirroir
d-i mirror/country string manual
d-i mirror/http/hostname string httpredir.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string

### Configuration d'apt
# On indique qu'on ne souhaite pas utiliser de mirroir
d-i apt-setup/use_mirror boolean false
d-i apt-setup/no_mirror boolean true
# On active les services security et updates
d-i apt-setup/services-select multiselect security, updates
d-i apt-setup/security_host string security.debian.org
# Notez qu'on ne peut pas modifier la chaîne pour updates.
# Ensuite, on indique quel est notre dépôt local (le premier qui démarre à 0)
d-i apt-setup/local0/repository string \
       http://debian.example.com/debian stable main contrib
# On peut même y mettre un commentaire qui sera injecté dans le fichier sources.list
d-i apt-setup/local0/comment string Serveur de paquets locaux de l'organisation

Vous pouvez tester plusieurs valeurs et ajouter d'autres dépôts (les backports par exemple).

Exemple de fichier de preseed qui automatise complètement le processus d'installation

Voici un des fichiers de preseed que j'utilise pour installer mon serveur de backup. L'installation est complètement automatique, sans aucune interaction de l'administrateur (hors manipulations pour booter sur l'image d'installation). Ce serveur est destiné à être remonté "from scratch" à partir de la simple clef USB qui contient également les paquets à installer et la configuration des principaux logiciels utilisés ainsi que la configuration système.

#### Fichier de preseed pour Debian jessie
# Configurer la locale permet aussi de configurer
# la langue et le pays de l'OS
d-i debian-installer/locale string fr_FR.UTF-8

# Choix du clavier
# keymap est un alias de keyboard-configuration/xkb-keymap
d-i keymap select fr(latin9)
# On désactive la sélection fine de la configuration du clavier
d-i keyboard-configuration/toggle select No toggling

### Configuration Réseau
# On désactive la configuration réseau
d-i netcfg/enable boolean false

# Mais on doit quand même configurer le nom de machine
d-i netcfg/get_hostname string testjessie
# Ainsi que le domaine
d-i netcfg/get_domain string example.com

# Ici, on définit le nom local de la machine
d-i netcfg/hostname string goofy

### Mirror settings
# Do not configure mirror repository
#d-i apt-setup/no_mirror boolean true
d-i mirror/country string manual
d-i mirror/http/hostname string debian.proxad.net
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string

### Configuration des comptes
# On indique le mot de passe root, sous forme d'un hash MD5 (echo "mypassword" | mkpasswd -s -H MD5)
d-i passwd/root-password-crypted password xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# On ne souhaite pas créer d'autres utilisateurs
d-i passwd/make-user boolean false

### Gestion de l'horloge
# L'horloge matérielle fonctionne sur la zone UTC
d-i clock-setup/utc boolean true

# La zone utilisée par l'OS sera celle de Paris
d-i time/zone string Europe/Paris

# On désactive l'utilisation de NTP pour configurer l'heure
d-i clock-setup/ntp boolean false

### Partitioning
# Nous voulons une table de partition au format GPT
d-i partman-basicfilesystems/choose_label string gpt
d-i partman-basicfilesystems/default_label string gpt
d-i partman-partitioning/choose_label string gpt
d-i partman-partitioning/default_label string gpt
d-i partman/choose_label string gpt
d-i partman/default_label string gpt
partman-partitioning partman-partitioning/choose_label select gpt

# Seul le premier disque est partionné
d-i partman-auto/disk string /dev/sda
# On partionne en "normal": pas de RAID ni de LVM
d-i partman-auto/method string regular
# Pour être sûr, on supprime une éventuelle configuration LVM
d-i partman-lvm/device_remove_lvm boolean true
# Même chose pour le RAID
d-i partman-md/device_remove_md boolean true
# Chaînes pour ne pas toucher la configuration LVM (donc pas de configuration)
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true

# L'installation sera simple: on fout tout dans une seule partition
d-i partman-auto/choose_recipe select atomic

# On valide sans confirmation la configuration de partman
d-i partman-md/confirm boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true

# fstab utilisera des UUID plutôt que des noms de périphériques
d-i partman/mount_style select uuid

### Installation du système
# On ne souhaite pas installer les paquets recommandés
# L'installation sera limitée aux paquets "essentials"
d-i base-installer/install-recommends boolean false

### Configuration d'apt
# On indique qu'on ne souhaite pas utiliser de mirroir
d-i apt-setup/use_mirror boolean false
d-i apt-setup/no_mirror boolean true
# On active les services security et updates
d-i apt-setup/services-select multiselect security, updates
d-i apt-setup/security_host string security.debian.org
# Notez qu'on ne peut pas modifier la chaîne pour updates.
# Ensuite, on indique quel est notre dépôt local (le premier qui démarre à 0)
d-i apt-setup/local0/repository string \
       http://debian.proxad.net/debian stable main contrib
# On peut même y mettre un commentaire qui sera injecté dans le fichier sources.list
d-i apt-setup/local0/comment string Serveur principal

# Pas d'envoi de rapport vers popcon
popularity-contest popularity-contest/participate boolean false

### Configuration de GRUB
# Seul Debian sera géré par GRUB
d-i grub-installer/only_debian boolean true

# Si on détecte un autre OS, on installera GRUB sur le MBR
d-i grub-installer/with_other_os boolean true

# On installe GRUB sur /dev/sda
d-i grub-installer/bootdev  string /dev/sda

## Suppression de paquets non désirés
d-i preseed/late_command string \
    in-target apt-get -y purge nano; \
    in-target apt-get -y purge vim-tiny; \
    in-target apt-get -y purge vim-common

### Fin de l'installation
# Désactivation du message indiquant que l'installation est terminée.
d-i finish-install/reboot_in_progress note

# Pas d'éjection du média d'installation (bien pour faire des tests sur une VM)
d-i cdrom-detect/eject boolean true

# Une fois l'installation terminée, on éteint la machine
d-i debian-installer/exit/poweroff boolean true

Aller plus loin: trouver les chaînes de preseed dans le code de d-i

Le guide d'installation de Debian donne un exemple assez complet de fichier preseed avec des explications dans les commentaires pour avoir une bonne idée de la majorité des chaînes de configuration. Néanmoins, il est parfois obligatoire d'utiliser une option peu courante ou non documentée dans l'exemple. C'est ce qui m'est arrivé avec les dépôts APT. J'ai dû fouiller le code de l'installeur pour avoir au moins le nom des options.

La recherche peut parfois être complexe. Le plus simple consiste à rechercher les fichiers .templates de debconf pour le module d-i que vous souhaitez explorer. Dans ces fichiers, vous trouverez le nom des variables et des paramètres ainsi que le texte des questions posées.

Pour cela vous pouvez utiliser Codesearch. Par exemple, vous souhaitez avoir plus d'informations sur les possibles questions sur le module apt-setup. Faîtes une recherche avec les bons paramètres sur Codesearch: path:/debian/* apt-setup. Vous trouverez tous les paquets qui contiennent la chaîne apt-setup dans le répertoire debian. Dans la liste des paquets, on trouve le paquet apt-setup. Ce dernier semble être le bon candidat car il est écrit dans sa description qu'il s'agit d'un module de d-i.

Si vous prenez le fichier apt-mirror-templates du répertoire debian, vous trouverez l'ensemble des chaînes de configuration disponibles pour cette partie de module. A vous de trouvez et de tester celle qui semble correspondre à vos besoins.

Veuillez noter que parfois, les chaîne de configuration ne sont pas forcément dans des fichiers avec une extension en .templates et il vous faudra fouiller dans l'arborescence debian du paquet pour trouver ce que vous cherchez.

Conclusions

Avec la méthode preseed, on peut donc installer Debian de manière complètement automatisée tout en bénéficiant de toutes les options présentes dans les boîtes de dialogues de l'installeur Debian. La plus grande difficulté sera de trouver les chaînes qui permettront de bien configurer la machine comme on le souhaite.

Attention, certains éléments ne sont pas gérés par l'installeur Debian et il faudra trouver une autre solution. Par exemple, si vous utilisez la configuration réseau via le mécanisme /etc/network, vous ne pourrez pas indiquer des scripts à lancer lors du lancement de l'interface (pre-up.d) avec l'installeur Debian. Il vous faudra un paquet de configuration ou utiliser un programme d'orchestration de configuration (Chef, Puppet, Ansible, Propellor, etc.)

Pour aller plus loin, vous pouvez utiliser deux programmes qui vous permettront d'industrialiser vos déploiements avec les fichiers preseed et même plus. Le premier se nomme simple-cdd. Il permet de construire des images ISO hybrides (bootables à partir de clef USB) à partir de simples fichiers de configuration. Vous pouvez ainsi gérer autant d'images ISO que vous voulez selon la configuration du système et les paquets que vous souhaitez utiliser. L'intérêt de simple-cdd est que l'image construite contient tous les paquets indispensables à l'installation de la machine. Vous pouvez même y ajouter des paquets que vous avez fabriqués. En une simple image ISO (ou une clef USB), vous pouvez donc reconstruire une machine "from scratch" et même sans accès au réseau local ou à Internet. Pour votre information, simple-cdd est un simple script shell qui est une surcouche à debian-cd. Ce dernier est le programme qui est utilisé pour fabriquer les images officielles de Debian et il est assez complexe à utiliser. Avec simple-cdd, quelques fichiers de configuration suffisent.

Le deuxième programme que j'utilise est l'ensemble des outils de config-package-dev qui permet de fabriquer un ou plusieurs paquets Debian dits "de configuration". Le principe est de mettre l'ensemble des fichiers de configuration spécifiques dans un répertoire de source et de créer un paquet Debian avec les outils config-package-dev. Par exemple, vous pouvez faire un paquet qui installe le fichier /etc/network/interface spécifique à une machine. L'installation de ce dernier sera gérée avec le sérieux de la gestion des paquets sous Debian. De plus, lorsque vous désinstallerez ce paquet de configuration, cette dernière reviendra à l'état initial (c'est-à-dire selon la configuration par défaut du mainteneur Debian ou la votre si elle a été customisée avant). En règle générale, je fais un paquet qui contient toute la configuration spécifique de la machine (réseau/configuration de grub/configuration du MTA système/netfilter/anonymisation IPv6/ajout de cacert dans les autorités de confiance/etc.). Ensuite, j'embarque ce paquet dans la configuration simple-cdd de la machine et à l'issue de l'installation, j'obtiens une machine prête à fonctionner et complètement configurée. Bien entendu, rien ne vous empêche de mettre ce paquet sur un dépôt local et d'orchestrer la configuration de vos machines avec. Vous pouvez même gérer ce paquet avec un gestionnaire de version pour pouvoir facilement revenir en arrière.

Cette méthode d'installation automatisée présente l'avantage d'utiliser uniquement des outils Debian et reste sans doute moins complexe que des logiciels d'orchestration de configuration classiques qui imposent de mettre en place toute une infrastructure pour ça et qui ne règlent pas le problème de l'installation initiale. C'est assez intéressant lorsqu'on gère des serveurs physiques hétérogènes notamment car ces derniers ne sont pas clonables facilement.

Posted lun. 05 oct. 2015 18:28:00

Introduction

Vous administrez votre propre serveur de courrier électronique: bravo, vous participez à décentraliser Internet et à lui donner un peu plus de résilience et de robustesse en plus de renforcer la protection de votre vie privée. Comme je l'ai déjà décrit il y a quelques années dans mes différents articles sur le courrier électronique, l'administration d'un ensemble de services (car il n'existe pas qu'un seul service) peut se révéler complexe. En conséquence, il vaut mieux y aller pas à pas, vérifier que tout ce qui est mis en place est correct et progressivement ajouter des services optionnels.

Aujourd'hui nous allons traiter des mesures destinées à renforcer la confiance que peut avoir le monde extérieur par rapport à votre domaine de courrier électronique. Cet article présentera 3 "protocoles" destinés à lutter contre le spam et à garantir l'authenticité de l'emetteur de messages électroniques. Ces trois protocoles seront, dans l'ordre, DKIM, SPF et DMARC. L'ensemble sera bien entendu appliqué, dans un cas concret, à une configuration existante sous Debian Jessie et son MTA par défaut: Exim4.

Mise en place de DKIM

A propos de DKIM

Avant de se lancer dans la configuration de DKIM, il faut essayer d'en comprendre les bases. Pour faire simple, DKIM est un système de signature de mails en sortie de votre MTA. La particularité de la signature c'est que la clef publique est disponible sur le serveur DNS qui dessert le domaine de courrier électronique.

Dans ce système, pas besoin d'autorité de certification, on va au plus simple en utilisant un champ TXT dans le DNS. Cette technique permet de garantir l'intégrité du message mais surtout de certifier que l'emetteur du message dispose du couple clef privée/clef publique dont cette dernière est référencée sur le serveur DNS du domaine de courrier électronique. Il y a donc de très grandes chances que l'émetteur soit légitime, c'est à dire, appartienne bien au domaine qu'il prétend annoncer dans le champ From (n'oubliez pas que dans les protocoles de courrier électronique, on peut mettre n'importe quel contenu dans le champ From par défaut).

Le système est donc assez simple mais il vous faut un serveur DNS sur lequel vous avez la main ou bien où vous pouvez ajouter un champ TXT (c'est le cas de la majorité des registrars qui fournissent un service DNS en plus de la location du nom de domaine).

Générer un couple clef privée/clef publique

La première étape est de générer un couple clef privée/clef publique. La première sera conservée bien au chaud sur votre serveur. La seconde sera exposée sur le serveur DNS du domaine.

-- génération de la clef privée
$ openssl genrsa -out example.com.dkim.pkey.pem 1024 -outform PEM
-- génération de la clef publique à partir de la clef publique
$ openssl rsa -in example.com.dkim.pkey.pem -out example.com.dkim.pem -pubout -outform PEM

Je vous conseille de générer ces clefs sur une machine disposant d'un certain niveau d'entropie. Concrètement, sur un plugcomputer, c'est plus difficile. Le faire sur une station de travail sera sans doute plus adapté.

Je vous conseille de déposer votre clef privée non pas dans le répertoire dédié (/etc/ssl/private) mais dans un répertoire accessible à l'utilisateur qui fait tourner le service exim4. En effet, exim4 tourne avec un utilisateur non privilégié (Debian-exim) qui ne peut accéder au précédent répertoire. Par commodité, je place la clef privée dans le répertoire de configuration d'Exim dans /etc/exim4/keys.

# cp example.com.dkim.pkey.pem /etc/exim4/keys/
# chgrp Debian-exim /etc/exim4/keys/example.com.dkim.pkey.pem
# chmod 640 /etc/exim4/keys/example.com.dkim.pkey.pem

Configuration de l'enregistrement DNS

Vous devez renseigner un champ TXT avec la syntaxe qui suit:

SELECTOR._domainkey.example.com IN TXT "k=rsa; p=PUBLICKEY"

SELECTOR indique un sélecteur de clef publique car on peut héberger plusieurs clefs publiques pour un même domaine. En guise de sélecteur, on peut mettre une date on un numéro d'identifiant. Pour ma part, je place une date, c'est bien suffisant, genre 20150806. N'oubliez pas le point à la fin du sélecteur.

PUBLICKEY est le contenu de votre clef publique sur une seule ligne.

Par exemple, voici le contenu du certificat de clef publique:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMKspwVBt2fpRXy0Yd+Ku+rzfG
cIiq80nEyNLQ4ZekA2MwqJmdGqyQxmCx0ddICrULOjcYpl+19UF0303jYsaLP6BP
A0bPTMu7k0ZGBXQxFG0tPsn0aDDOeW4HonX1uN7sM+IAR3bXzuLcObYEzTQkPIko
/O8M6PeVdrKWfFgPFwIDAQAB
-----END PUBLIC KEY----

Sur une seule ligne, ça donne:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMKspwVBt2fpRXy0Yd+Ku+rzfGcIiq80nEyNLQ4ZekA2MwqJmdGqyQxmCx0ddICrULOjcYpl+19UF0303jYsaLP6BPA0bPTMu7k0ZGBXQxFG0tPsn0aDDOeW4HonX1uN7sM+IAR3bXzuLcObYEzTQkPIko/O8M6PeVdrKWfFgPFwIDAQAB

Pour vérifier la configuration DNS, utilisez dig:

$ dig -t TXT SELECTOR._domainkey.example.com +short
"k=rsa\; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMKspwVBt2fpRXy0Yd+Ku+rzfGcIiq80nEyNLQ4ZekA2MwqJmdGqyQxmCx0ddICrULOjcYpl+19UF0303jYsaLP6BPA0bPTMu7k0ZGBXQxFG0tPsn0aDDOeW4HonX1uN7sM+IAR3bXzuLcObYEzTQkPIko/O8M6PeVdrKWfFgPFwIDAQAB"

Configuration d'Exim4

Maintenant que nous avons traité la question des clefs, il reste à indiquer à Exim4 d'utiliser notre clef privée. J'utilise le démon light mais la configuration est identique pour le démon heavy.

Si vous suivez les règles Debian sur Exim4 (vous devriez), le plus simple consiste à modifier le fichier /etc/exim4/conf.d/main/000_localmacros que j'ai déjà utilisé dans mes articles précédents. Voici le contenu à ajouter:

# Configuration DKIM
DKIM_CANON = relaxed
DKIM_SELECTOR = SELECTOR
DKIM_DOMAIN = example.com
DKIM_PRIVATE_KEY = /etc/exim4/keys/example.com.dkim.pkey.pem

N'utilisez pas la macro DKIM_FILE: elle n'est pas valide pour cette version d'Exim4.

Ensuite, le classique:

# update-exim4.conf
# systemctl restart exim4

Allez faire un tour dans les logs /var/log/exim4/mainlog pour voir s'il n'y aurait pas de problème dans votre configuration.

Tester la configuration

Le plus simple des tests consiste à envoyer un courrier électronique de votre MTA vers un correspondant extérieur qui dispose de quoi vérifier DKIM. Pour ma part, j'utilise un compte GMail qui gère DKIM et j'affiche le contenu original (seule manière d'avoir les en-têtes complètes dans GMail). Vous devriez voir des choses comme ce qui suit:

       dkim=pass header.i=@example.com
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=example.com; s=SELECTOR;
       h=Content-Type:MIME-Version:Message-ID:Subject:To:From:Date; bh=epN+8Ir4gghSKMRQcJJjbBdVZhDiHfJEakMbvPyEbWw=;
       b=EDgHfrk5brLGxRHD4JwefivY2163CFDm8yu2RVbl66D+CAFRXScZIrclMDA4wF4oX9a8lSo39LDhaGIgl85MfkwvDHGk7tbcG7mcIOpVZGgesS3zI+ifSVAD210JEI3y9WwwpmJQOwJJ3CnUAcV2lo0dLydDpzmAKdOz/ohv1DQ=;

Mise en place de SPF

Introduction

Après avoir travaillé sur l'implémentation de DKIM, il nous reste à voir ce qui se passe du côté de SPF. Il s'agit d'un mécanisme permettant d'identifier les courriers électroniques usurpés. Pour faire simple, il s'agit d'un enregistrement DNS (un autre) permettant de lister quelles sont les adresses IP légitimes pour envoyer du courrier électronique pour ce domaine précis. La vérification se fait au niveau du MTA entrant donc vous n'aurez rien à faire au niveau du MTA sortant.

Concrètement, le MTA qui reçoit le courrier électronique de votre MTA va faire une requête DNS pour récupérer une information SPF. Si celle-ci existe, elle sera analysée pour vérifier si le MTA qui envoie le courrier correspond à la plage (ou les plages) d'adresses IP déclarée(s) dans le DNS.

Déclaration au niveau du DNS

SPF n'est qu'un (ou plusieurs) enregistrement(s) TXT simple(s) dont voici la forme:

"v=spf1 Règle_1 [Règle_2] ... [Règle_N] NON_MATCHING"

Quelques explications basiques:

  • v=spf1 permet d'identifier que le champ TXT est un champ SPF.
  • Règle correspond à un ou plusieurs caractères dont la syntaxe est la suivante:
    • a: cette règle est simple et n'a pas de paramètres. Concrètement, si le domaine dispose d'une adresse IP déclarée dans le DNS, ce qui veut dire que le domaine dispose d'une adresse IP résolue au niveau du nom de domaine seul, alors cette adresse est reprise et considérée comme légitime pour envoyer du courrier électronique. Cette règle s'applique sur les hébergements très simples où tout est concentré sur une seule machine (c'est souvent le cas pour de l'autohébergement).
    • mx: cette règle est également simple et ne dispose pas non plus de paramètres. Dans ce cas, si le domaine dispose d'un enregistrement DNS MX, tous les serveurs retournés par une requête DNS MX sont déclarés comme légitimes. C'est également une situation simple qui permet de prendre en compte plusieurs serveurs de mail pour un seul domaine de courrier électronique.
    • ip4: liste une adresse IPv4 ou une plage d'adresses IPv4 comme étant légitimes pour envoyer du courrier électronique. la syntaxe est du type: ip4:xxx.xxx.xxx.xxx pour les IPv4 simples ou ip4:xxx.xxx.xxx.xxx/yy pour les plages.
    • ip6: liste une adresse IPv6 ou une plage d'adresses IPv6 comme étant légitimes pour envoyer du courrier électronique. la syntaxe est du type: ip6:xxxx:xxxx:..:xx pour les IPv6 simples ou ip6:xxxx:xxxx:..:xxxx/yy pour les plages.
  • NON_MATCHING: permet de dire quoi faire quand une IP n'est pas dans les cas de figure des règles. On utilise le mot all avec un préfixe qui peut être + (accepter quand même), - (rejet), ~ (accepter mais marquer).

Dans notre cas, nous souhaitons utiliser les règles a et mx et rejeter tous les autres cas. La chaîne TXT prend donc la forme suivante:

"v=spf1 a mx -all"

Vérifier la déclaration DNS

Une simple requête dig sur les champs TXT permet de voir si votre enregistrement DNS est actif:

$ dig example.com TXT +short
"v=spf1 a mx -all"

Tester la configuration

Le plus simple des tests consiste à envoyer un courrier électronique de votre MTA vers un correspondant extérieur qui dispose de quoi vérifier SPF. Pour ma part, j'utilise un compte GMail et j'affiche le contenu original (seule manière d'avoir les en-têtes complètes dans GMail). Vous devriez voir des choses comme ce qui suit:

Authentication-Results: mx.google.com;
       spf=pass (google.com: domain of user@example.com designates xxx.xxx.xxx.xxx as permitted sender) smtp.mail=user@example.com;

Mise en place de DMARC

Introduction

DKIM et SPF permettent d'améliorer la détection des mails usurpés mais il persiste un grand vide: DKIM n'est pas obligatoire. Ainsi, n'importe qui se trouvant au sein de votre réseau (si ce dernier est déclaré dans SPF) peut envoyer un email sans signature DKIM.

Il faut donc un moyen de dire que DKIM est obligatoire. C'est le but de DMARC.

Déclaration DNS

DMARC consiste en un (ou plusieurs) enregistrement(s) DNS TXT qui indique(nt) quelles sont les règles à respecter au niveau de DKIM et de SPF au sujet des courriers électroniques.

Sa syntaxe est la suivante:

"v=DMARC1; p=[REJECT]; adkim=[REGLE_DKIM]; aspf=[REGLE_SPF]"
  • REJECT indique quelle est la politique à mener en cas de rejet. On peut utiliser les mots suivants: none (accepter), reject (rejeter), ou quarantine (mettre en quarantaine).
  • REGLE_DKIM indique ce qu'il faut faire en cas de non respect de DKIM (le mail n'a pas de signature DKIM). On peut utiliser les lettres suivantes: r (mode relaché, on accepte le courriel) ou s (mode strict, on rejette le courriel).
  • REGLE_SPF indique ce qu'il faut faire en cas de non respect de SPF (le mail provient d'une machine non déclarée dans SPF). On peut utiliser les lettres suivantes: r (mode relaché, on accepte le courriel) ou s (mode strict, on rejette le courriel).

En plus de ces règles on peut utiliser d'autres paramètres:

  • fo: indique comment rédiger les formulaires d'alertes qui seront envoyés à l'administrateur du domaine de courrier électronique. 0 indique d'envoyer un rapport si l'ensemble des règles ne sont pas respectées, 1 indique d'envoyer un rapport si un seul des éléments (DKIM ou SPF) n'est pas respecté.
  • rua: indique l'adresse email utilisée pour récupérer les rapports d'alerte.

Dans notre cas, notre règle DMARC sera la suivante:

"v=DMARC1; p=reject; adkim=s; aspf=s; fo:1; rua:postmaster@example.com"

Conclusion

Finalement, les mécanismes de vérification de l'identité de l'émetteur d'un courrier électronique sont assez simples à comprendre et à mettre en place. Même sur une configuration légère auto-hébergée, il est donc facile de les mettre en oeuvre. Sur ce plan, ils deviennent, au fur et à mesure du temps, des quasi pré-requis. Sachez que Google Mail les utilise depuis de nombreuses années pour garantir la validité des courriers électroniques que vous envoyez sur le domaine gmail.com (en plus d'autres mécanismes bien plus contraignants comme la résolution de nom inverse qu'on ne maîtrise pas toujours lorsqu'on s'auto-héberge).

Ne vous privez donc pas de les mettre en place !

Références

DKIM:

SPF:

DMARC:

Bonus: multidomaine DKIM

Notre configuration DKIM est sympathique mais il est probable que vous ayez plusieurs domaines de courrier électroniques qui pointent vers le même MTA. Dans ce cas, comment gérer un domaine qui change en fonction des messages qui sont envoyés ?

Exim4 est assez performant: sa configuration permet de calculer des contenus de variables en fonction de règles pré-établies. Exim4 embarque donc un quasi-langage (lire sa documentation) le rendant ultra-dynamique. Exploitons ces mécanismes avec une configuration multidomaine pour DKIM.

Voici cette configuration et les explications qui vont avec:

# Configuration DKIM
DKIM_CANON = relaxed
DKIM_SELECTOR =    SELECTOR
DKIM_DOMAIN = ${sg{${lc:${domain:$h_from:}}}{^www\.}{}}
DKIM_FILE = /etc/exim4/keys/DKIM_DOMAIN.dkim.pkey.pem
DKIM_PRIVATE_KEY = ${if exists {DKIM_FILE} {DKIM_FILE}{0}}

Vous devez noter que vos sélecteurs seront identiques pour toutes les déclarations DNS des clefs publiques. On commence par calculer le domaine dans la variable DKIM_DOMAIN. $h_from permet d'extraire le contenu du champ From: du message à envoyer. ${domain:$h_from} permet d'extraire le nom de domaine de la variable h_from. ${lc:${VAR}} permet de mettre en minuscule le nom de domaine. Enfin, la directive $sg permet de jouer une expression régulière. Ici, il s'agit d'éliminer un éventuel www. qui pointerait dans le nom de domaine (on aurait pu s'en passer).

Ensuite, DKIM_FILE contient le nom du fichier de clef privée. Notez bien que la variable DKIM_DOMAIN est utilisée directement. Vos noms de clefs privées doivent être du genre: domaine_fqdn.dkim.pkey.pem et situées dans /etc/exim4/keys/.

Enfin, DKIM_PRIVATE_KEY exécute un test pour savoir si le fichier déclaré dans DKIM_FILE existe. Si c'est le cas, la variable DKIM_PRIVATE_KEY contiendra le contenu de DKIM_FILE, sinon, elle ne contiendra rien. Lorsque la variable DKIM_PRIVATE_KEY est vide, Exim4 désactive la signature DKIM pour les messages sortants.

Posted jeu. 06 août 2015 13:19:35 Tags:

Introduction

A la suite de notre article sur l'installation manuelle du client Oracle 12c sous Debian, j'avais émis l'hypothèse de créer un ensemble de paquets facilement déployables sous Debian. Ce sera l'objet de cet article qui va nous plonger un peu dans la création de paquets Debian.

Pour commencer, je ne suis pas développeur Debian. Donc je ne suis pas un spécialiste de la chose (même si je m'entraîne régulièrement). Je vais donc faire des erreurs ou des choix qui ne seront pas appropriés. Mais mon objectif est d'obtenir des paquets Debian permettant d'installer facilement le client Oracle via dpkg.

Ensuite, sachez qu'à moins d'un coup de tonnerre dans le Landerneau, la licence du client Oracle ne permettra JAMAIS d'envisager son inclusion dans la distribution Debian (même dans non-free). Je ne pourrais non plus JAMAIS distribuer ces paquets prêts à l'emploi.

Enfin, distribuer des binaires purs déjà compilés dans un paquet Debian est un travail particulier. En effet, la majorité des paquets Debian (et donc des outils qui vont avec) sont créés à partir de sources qu'il faut compiler. Ici, nous avons juste un ensemble de fichiers qu'il s'agira de répartir comme il faut sur le système.

Vous êtes prévenus, passons à la suite...

Télécharger ce qu'il faut

Il vous faut:

  • le client Oracle 11g nommé Instant Client.
  • le SDK Oracle 11g qui est nécéssaire pour compiler le provider Oracle de QGIS ou d'autres bibliothèques telles que cx_Oracle.
  • le binaire de SQLPlus 11g, le client SQL en ligne de commande d'Oracle. Il n'est pas nécéssaire pour la suite mais sa présence vous permettra de tester la connexion vers votre serveur Oracle Database.

Prenez soin de prendre la version adaptée à votre architecture (X86 32 ou 64 bits) et stockez ces archives dans le répertoire ~/projects/oracle/oic/.

J'ai pris le client 11g pour des questions techniques (je vais compiler le client Oracle Spatial QGIS avec cette version) mais je pense qu'on peut faire le même travail pour la version 12c sans trop de souci.

Ce que nous allons produire

Pour ma part, j'ai choisi de créer trois paquets:

  • oracle-instantclient-11.2.0.4-1.deb qui contiendra la base de l'installation, c'est à dire, tout ce qui se trouve dans le client Oracle basique, ses binaires comme ses bibliothèques partagées.
  • oracle-instantclient-dev-11.2.0.4-1.deb qui contiendra le SDK.
  • oracle-sqlplus-11.2.0.4-1.deb qui contiendra le binaire SQLPus.

Il y aura bien sûr une interdépendance entre les paquets. Plutôt que de tout mettre dans /opt, je vais installer l'ensemble des fichiers dans le système standard Debian mais en respectant les chemins qu'on peut trouver dans les paquets RPM fournis par Oracle. En effet, l'objectif est de se conformer le plus possible à la charte Debian tout en permettant à la majorité des programmes qui se basent sur Oracle de trouver les bibliothèques. De fait, la charte Debian interdit de mettre des fichiers dans /opt et dans /usr/local. Donc autant tout mettre au bon endroit directement. De plus, la désinstallation via apt permettra facilement de retirer l'ensemble des fichiers en cas de problème, sans pourrir le reste du système (enfin, si on travaille bien).

Un peu de théorie sur les paquets Debian

Pour mieux comprendre ce que nous allons faire, vous DEVEZ lire le guide du nouveau mainteneur Debian.

Dans la pratique, nous allons créer des paquets Debian simples qui ne font que copier des fichiers au bon endroit. C'est un type de paquet spécial mais assez facile à comprendre: il n'y a pas de phase de compilation.

Pour résumer, voici les éléments à intégrer avant de commencer:

  • On créé un répertoire dédié à chaque paquet.
  • Dans ce répertoire, on dézippe chaque archive du client Oracle selon le nom du paquet.
  • On créé ensuite un répertoire debian à la racine du répertoire dédié.
  • Dans ce répertoire debian, on créé les fichiers nécessaires à la création du paquet.
  • Pour faire simple, on va surtout déclarer où placer les fichiers Oracle dans le système cible.
  • Ensuite, nous allons utiliser les outils debian pour créer le paquet (via dpkg-buildpackage).

Avant de nous plonger dans le travail, créez les répertoires dédiés à l'empaquetage:

$ mkdir -p ~/projects/oracle/packaging/oracle-instantclient/debian
$ mkdir -p ~/projects/oracle/packaging/oracle-sqlplus/debian
$ mkdir -p ~/projects/oracle/packaging/oracle-instantclient-dev/debian
$ cd ~/projects/oracle/packaging/oracle-instantclient && unzip ~/projects/oracle/oic/instantclient-basic-linux.x64-11.2.0.4.0.zip
$ cd ~/projects/oracle/packaging/oracle-sqlplus && unzip ~/projects/oracle/oic/instantclient-sqlplus-linux.x64-11.2.0.4.0.zip
$ cd ~/projects/oracle/packaging/oracle-instantclient-dev && unzip ~/projects/oracle/oic/instantclient-sdk-linux.x64-11.2.0.4.0.zip

Paquet oracle-instantclient-11.2.0.4-1.deb

Introduction

Les fichiers binaires sont dans le répertoire ~/projects/oracle/packaging/oracle-instantclient/instantclient_11_2. Nous allons créer un ensemble de fichiers pour l'empaquetage Debian. Ces derniers sont dans ~/projects/oracle/packaging/oracle-instantclient/debian/ et je vais les présenter un par un...

Fichier control

Ce fichier permet de définir les informations de dépendances du paquet ainsi que le nom précis et les éléments qui se retrouveront dans les métadonnées du paquet. Voici son contenu adapté:

Source: oracle-instantclient
Section: non-free/database
Priority: extra
Maintainer: Médéric Ribreux <mederic.ribreux@medspx.fr>
Build-Depends: debhelper (>= 9.0.0~)
Standards-Version: 3.9.6

Package: oracle-instantclient
Architecture: amd64
Depends: ${misc:Depends}, libaio1
Description: Oracle Instant Client base package
 Instant Client allows you to run your applications without installing
 the standard Oracle client or having an ORACLE_HOME. OCI, OCCI,
 Pro*C, ODBC, and JDBC applications work without modification, while
 using significantly less disk space than before.

On voit que le paquet dépend notamment de libaio1 et j'ai indiqué un petit blabla pour plus d'informations.

Fichier changelog

Ce fichier permet de présenter les informations sur l'évolution du packaging ainsi que de préciser le numéro de version du paquet.

[[! format bash """ oracle-instantclient (11.2.0.4.0-1) unstable; urgency=low

"""]]

Fichier compat

Ce fichier précise quelle est la version de système d'empaquetage que nous utilisons (dans notre cas, il s'agit de debhelper v9).

9

Fichier README.Debian

Ce fichier indique des informations sur le contenu du paquet. J'ai fait un petit blabla sur les autres utilitaires présent dans les binaires livrés par Oracle.

Oracle Instant Client for Debian
--------------------------------

This package install the basic Oracle Instant Client on a Debian
system. This package only install the libraries and the executable
binaries into the Debian system. Ths package can only work for x86_64
systems as Oracle Corporation only provides binaries for this
plateform.

To use a tnsnames.ora file, you have to export the TNS_ADMIN
environment variable on a per-user configuration. I suggest you use
the following:

  $ mkdir ~/.oracle
  $ mv tnsnames.ora ~/.oracle/
  $ echo "# TNSNAMES for Oracle" >> ~/.profile
  $ echo "export TNS_ADMIN=~/.oracle/" >> ~/.profile

With this package, you will also find the following tools:

* adcri: ADR Command Interpreter
  The ADR Command Interpreter (ADRCI) is a command-line tool that you
  use to manage Oracle Database diagnostic data.
* genezi: Generate EZ Instantclient
  Instant Client (i.e. no sqlplus) from 10.2.0.3 up can run
  LD_LIBRARY_PATH=$ORACLE_HOME/lib genezi -v to get client
  version.
* uidrvci: ADR related. E.g., uidrvci
  /u01/app/oracle/diag/rdbms/db_name/instance_name/trace getSchema
  INC_METER_SUMMARY, where INC_METER_SUMMARY is an .ams file under the
  trace/metadata subdir of the directory in the second arg. This
  getSchema command shows the table definition of v$incmeter_summary
  (summary of incident meters). Not sure what use this command really
  has.

Fichier rules

C'est le fichier le plus important: il indique comment compiler le paquet. Dans notre cas, il y juste des fichiers à copier donc le fichier rules est très simple. Il repose sur d'autres fichiers (install, docs, etc.) pour paramétrer quoi faire.

#!/usr/bin/make -f

clean:
   dh_clean

%:
   dh $@

Fichier install

Ce fichier indique quels sont les fichiers à copier et où doivent-ils être copiés. Dans notre cas, nous allons effectuer une installation directement dans le système d'exploitation pour nous conformer à la charte Debian. La majorité se retrouve dans /usr/lib/oracle/11.2/client64/lib mais il y a quelques binaires qui vont se retrouver dans /usr/bin. Enfin, les jar ont vocation à être dans /usr/share/java.

instantclient_11_2/adrci usr/lib/oracle/11.2/client64/bin
instantclient_11_2/genezi usr/lib/oracle/11.2/client64/bin
instantclient_11_2/uidrvci usr/lib/oracle/11.2/client64/bin
instantclient_11_2/libclntsh.so.11.1 usr/lib/oracle/11.2/client64/lib
instantclient_11_2/libocci.so.11.1 usr/lib/oracle/11.2/client64/lib
instantclient_11_2/libnnz11.so usr/lib/oracle/11.2/client64/lib
instantclient_11_2/libociei.so usr/lib/oracle/11.2/client64/lib
instantclient_11_2/libocijdbc11.so usr/lib/oracle/11.2/client64/lib
instantclient_11_2/ojdbc5.jar usr/lib/oracle/11.2/client64/lib
instantclient_11_2/ojdbc6.jar usr/lib/oracle/11.2/client64/lib
instantclient_11_2/xstreams.jar usr/lib/oracle/11.2/client64/lib
oracle-instantclient.conf etc/ld.so.conf.d

Le répertoire /usr/lib/oracle/11.2/client64/ correspond à l'emplacement d'installation du paquet RPM officiel d'Oracle. C'est cet emplacement que nous allons utiliser car de nombreux programmes s'attendent à le trouver à cet endroit. C'est le cas de QGIS par exemple.

Par ailleurs, ces fichiers étants situés dans des emplacements non standards pour le linker dynamique, il faut ajouter un fichier dans /etc/ld.so.conf.d/. Ce dernier permettra d'ajouter les bibliothèques présentes dans /usr/lib/oracle/11.2/client64/lib dans le chemin de recherche du linker dynamique du système. C'est un peu crade (j'aurais pu mettre tout dans /usr/lib et /usr/bin) mais j'ai préferré suivre ce qui avait été fait pour le RPM tout en permettant de lancer sqlplus directement en ligne de commande, sans créer la variable d'environnement ORACLE_HOME. Le contenu du fihcier est présenté un peu plus bas...

Fichier docs

Ce fichier indique quels sont les fichiers de doc qui vont se retrouver dans /usr/share/doc/oracle-instantclient/

instantclient_11_2/BASIC_README

Ce fichier indique quels sont les liens symboliques à réaliser lors de l'installation du paquet. Pour notre part, nous devons créer le lien vers libclntsh.so (comme vu dans la procédure manuelle).

usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1 usr/lib/oracle/11.2/client64/lib/libclntsh.so
usr/lib/oracle/11.2/client64/lib/libocci.so.11.1 usr/lib/oracle/11.2/client64/lib/libocci.so

Fichier shlibs

Le paquet oracle-instantclient installe des binaires mais également des bibliothèques partagées. Sous Debian, il faut respecter certaines règles, notamment pour indiquer quelles sont les bibliothèques que le paquet installe. Cela permet aux autres paquets Debian qui vont utiliser ces bibliothèques de déterminer automatiquement quel sont les dépendances vers les paquets qui embarques ces bibliothèques partagées.

Voici le contenu du fichier:

libclntsh       11.1   oracle-instantclient (>= 11.2)
libnnz11        11.1   oracle-instantclient (>= 11.2)
libocci        11.1    oracle-instantclient (>= 11.2)
libociei   11.1    oracle-instantclient (>= 11.2)
libocijdbc11   11.1    oracle-instantclient (>= 11.2)

Chaque ligne indique le nom global de la bibliothèque partagée, suivi du numéro de version (11.1 tel que le SONAME l'indique). On trouve en fin de chaque ligne, le nom du paquet concerné.

A l'issue de l'installation, le contenu de ce paquet est déposé dans /var/lib/dpkg/info/oracle-instantclient.shlibs.

C'est la manière la plus simple que j'ai trouvée pour indiquer les dépendances pour les bibliothèques partagées pour qu'elles puissent être identifiées par les programmes tiers. Il existe également la version avec les fichiers de symbôles mais c'est, de mon point de vue, plus compliqué à gérer.

Dans la pratique, lorsqu'on travaille avec les sources du programme, cette opération est réalisée quasiment automatiquement par les programmes de création de paquets Debian. Dans notre cas, nous n'avons que des binaires et nous devons créer cette information à la main.

Fichier copyright

Il s'agit du fichier qui précise les licences des différents composants du paquet, y compris les fichiers Debian. Il repose sur une norme précise. Pour ma part, j'ai ajouté la totalité de la licence Oracle (juste pour faire propre) d'où la taille du fichier.

Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=135
Name: oracle-instantclient
Maintainer: Médéric Ribreux <mederic.ribreux@medspx.fr>
Source: http://medspx.fr

Files: instantclient_11_2/*
Copyright: 2013 Oracle Corporation
License: Oracle Technology Network Development and Distribution License Terms for Instant Client

Files: debian/*
Copyright: 2015 Médéric Ribreux <mederic.ribreux@medspx.fr>
License: GPL-2+

License: GPL-2+
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.
 .
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.
 .
 You should have received a copy of the GNU General Public License along
 with this program; if not, write to the Free Software Foundation, Inc.,
 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 .
 On Debian systems, the full text of the GNU General Public
 License version 2 can be found in the file
 `/usr/share/common-licenses/GPL-2'.

License: Oracle Technology Network Development and Distribution License Terms for Instant Client
 Export Controls on the Programs
 
 Selecting the "Accept License Agreement" button is a confirmation of
 your agreement that you comply, now and during the trial term, with
 each of the following statements:

 -You are not a citizen, national, or resident of, and are not under
 control of, the government of Cuba, Iran, Sudan, Libya, North Korea,
 Syria, nor any country to which the United States has prohibited
 export.
 -You will not download or otherwise export or re-export the Programs,
 directly or indirectly, to the above mentioned countries nor to
 citizens, nationals or residents of those countries.
 -You are not listed on the United States Department of Treasury lists
 of Specially Designated Nationals, Specially Designated Terrorists,
 and Specially Designated Narcotic Traffickers, nor are you listed on
 the United States Department of Commerce Table of Denial Orders.

 You will not download or otherwise export or re-export the Programs,
 directly or indirectly, to persons on the above mentioned lists.

 You will not use the Programs for, and will not allow the Programs to
 be used for, any purposes prohibited by United States law, including,
 without limitation, for the development, design, manufacture or
 production of nuclear, chemical or biological weapons of mass
 destruction.

 EXPORT RESTRICTIONS
 You agree that U.S. export control laws and other applicable export
 and import laws govern your use of the programs, including technical
 data; additional information can be found on Oracle®'s Global Trade
 Compliance web site (http://www.oracle.com/products/export).

 You agree that neither the programs nor any direct product thereof
 will be exported, directly, or indirectly, in violation of these
 laws, or will be used for any purpose prohibited by these laws
 including, without limitation, nuclear, chemical, or biological
 weapons proliferation.

 Oracle Employees: Under no circumstances are Oracle Employees
 authorized to download software for the purpose of distributing it to
 customers. Oracle products are available to employees for internal
 use or demonstration purposes only. In keeping with Oracle's trade
 compliance obligations under U.S. and applicable multilateral law,
 failure to comply with this policy could result in disciplinary
 action up to and including termination.

 Note: You are bound by the Oracle Technology Network ("OTN") License
 Agreement terms. The OTN License Agreement terms also apply to all
 updates you receive under your Technology Track subscription.

 The OTN License Agreement terms below supercede any shrinkwrap
 license on the OTN Technology Track software CDs and previous OTN
 License terms (including the Oracle Program License as modified by
 the OTN Program Use Certificate).

 Oracle Technology Network Development and Distribution License
 Agreement for Instant Client

 "We," "us," and "our" refers to Oracle America, Inc. "You" and "your"
 refers to the individual or entity that wishes to use the Programs
 from Oracle under this Agreement. "Programs" refers to the Software
 Products referenced below that you wish to download and use and
 Program documentation. "License" refers to your right to use the
 Programs and Program documentation under the terms of this
 Agreement. The substantive and procedural laws of California govern
 this Agreement. You and Oracle agree to submit to the exclusive
 jurisdiction of, and venue in, the courts of San Francisco, San
 Mateo, or Santa Clara counties in California in any dispute arising
 out of or relating to this Agreement.

 We are willing to license the Programs to you only upon the condition
 that you accept all of the terms contained in this Agreement. Read
 the terms carefully and select the "Accept" button at the bottom of
 the page to confirm your acceptance. If you are not willing to be
 bound by these terms, select the "Do Not Accept" button and the
 registration process will not continue.

 Software Product
 - Instant Client
 
 License Rights

 License.
 We grant you a non-exclusive right and license to use the Programs
 solely for your business purposes and development and testing
 purposes, subject to the terms of this Agreement. You may allow third
 parties to use the Programs, subject to the terms of this Agreement,
 provided such third party use is for your business operations only.

 Distribution License
 We grant you a non-exclusive right and license to distribute the
 Programs, provided that you do not charge your end users for use of
 the Programs. Your distribution of such Programs shall at a minimum
 include the following terms in an executed license agreement between
 you and the end user that: (1) restrict the use of the Programs to
 the business operations of the end user; (2) prohibit (a) the end
 user from assigning, giving, or transferring the Programs or an
 interest in them to another individual or entity (and if your end
 user grants a security interest in the Programs, the secured party
 has no right to use or transfer the Programs); (b) make the Programs
 available in any manner to any third party for use in the third
 party's business operations (unless such access is expressly
 permitted for the specific program license or materials from the
 services you have acquired); and (c) title to the Programs from
 passing to the end user or any other party; (3) prohibit the reverse
 engineering (unless required by law for interoperability),
 disassembly or decompilation of the Programs and prohibit duplication
 of the Programs except for a sufficient number of copies of each
 Program for the end user's licensed use and one copy of each Program
 media; (4) disclaim, to the extent permitted by applicable law, our
 liability for any damages, whether direct, indirect, incidental, or
 consequential, arising from the use of the Programs; (5) require the
 end user at the termination of the Agreement, to discontinue use and
 destroy or return to you all copies of the Programs and
 documentation; (6) prohibit publication of any results of benchmark
 tests run on the Programs; (7) require the end user to comply fully
 with all relevant export laws and regulations of the United States
 and other applicable export and import laws to assure that neither
 the Programs, nor any direct product thereof, are exported, directly
 or indirectly, in violation of applicable laws; (8) do not require us
 to perform any obligations or incur any liability not previously
 agreed to between you and us; (9) permit you to audit your end user's
 use of the Programs or to assign your right to audit the end user's
 use of the Programs to us; (10) designate us as a third party
 beneficiary of the end user license agreement; (11) include terms
 consistent with those contained in the sections of this Agreement
 entitled "Disclaimer of Warranties and Exclusive Remedies," "No
 Technical Support," "End of Agreement," "Relationship Between the
 Parties," and "Open Source"; and (11) exclude the application of the
 Uniform Computer Information Transactions Act.

 You may allow your end users to permit third parties to use the
 Programs on such end user's behalf for the purposes set forth in the
 end user license agreement, subject to the terms of such
 agreement. You shall be financially responsible for all claims and
 damages to us caused by your failure to include the required
 contractual terms set forth above in each end user license agreement
 between you and an end user. We are a third party beneficiary of any
 end user license agreement between you and the end user, but do not
 assume any of your obligations thereunder, and you agree that you
 will not enter into any end user license agreement that excludes us
 as a third party beneficiary and will inform your end users of our
 rights.

 If you want to use the Programs for any purpose other than as
 expressly permitted under this Agreement you must contact us to
 obtain the appropriate license. We may audit your use of the
 Programs. Program documentation is either shipped with the Programs,
 or documentation may be accessed online at
 http://www.oracle.com/technetwork/indexes/documentation/index.html.

 You agree to: (a) defend and indemnify us against all claims and
 damages caused by your distribution of the Programs in breach of this
 Agreement and/or failure to include the required contractual
 provisions in your end user agreement as stated above; (b) keep
 executed end user agreements and records of end user information
 including name, address, date of distribution and identity of
 Programs distributed; (c) allow us to inspect your end user
 agreements and records upon request; and, (d) enforce the terms of
 your end user agreements so as to effect a timely cure of any end
 user breach, and to notify us of any breach of the terms.

 Ownership and Restrictions
 We retain all ownership and intellectual property rights in the
 Programs. You may make a sufficient number of copies of the Programs
 for the licensed use and one copy of the Programs for backup
 purposes.

 You may not:
 -use the Programs for any purpose other than as provided above;
 -charge your end users for use of the Programs;
 -remove or modify any Program markings or any notice of our
 proprietary rights;
 -assign this agreement or give the Programs, Program access or an
 interest in the Programs to any individual or entity except as
 provided under this agreement;
 -cause or permit reverse engineering (unless required by law for
 interoperability), disassembly or decompilation of the Programs;
 -disclose results of any Program benchmark tests without our prior
 consent.

 Export
 You agree that U.S. export control laws and other applicable export
 and import laws govern your use of the Programs, including technical
 data; additional information can be found on Oracle's Global Trade
 Compliance web site located at
 http://www.oracle.com/products/export/index.html. You agree that
 neither the Programs nor any direct product thereof will be exported,
 directly, or indirectly, in violation of these laws, or will be used
 for any purpose prohibited by these laws including, without
 limitation, nuclear, chemical, or biological weapons proliferation.

 Disclaimer of Warranty and Exclusive Remedies

 THE PROGRAMS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. WE
 FURTHER DISCLAIM ALL WARRANTIES, EXPRESS AND IMPLIED, INCLUDING
 WITHOUT LIMITATION, ANY IMPLIED WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.

 IN NO EVENT SHALL WE BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
 PUNITIVE OR CONSEQUENTIAL DAMAGES, OR DAMAGES FOR LOSS OF PROFITS,
 REVENUE, DATA OR DATA USE, INCURRED BY YOU OR ANY THIRD PARTY,
 WHETHER IN AN ACTION IN CONTRACT OR TORT, EVEN IF WE HAVE BEEN
 ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. OUR ENTIRE LIABILITY FOR
 DAMAGES HEREUNDER SHALL IN NO EVENT EXCEED ONE THOUSAND DOLLARS
 (U.S. $1,000).

 No Technical Support
 Our technical support organization will not provide technical
 support, phone support, or updates to you or end users for the
 Programs licensed under this agreement.

 Restricted Rights
 If you distribute a license to the United States government, the
 Programs, including documentation, shall be considered commercial
 computer software and you will place a legend, in addition to
 applicable copyright notices, on the documentation, and on the media
 label, substantially similar to the following:
 NOTICE OF RESTRICTED RIGHTS
 "Programs delivered subject to the DOD FAR Supplement are 'commercial
 computer software' and use, duplication, and disclosure of the
 programs, including documentation, shall be subject to the licensing
 restrictions set forth in the applicable Oracle license
 agreement. Otherwise, programs delivered subject to the Federal
 Acquisition Regulations are 'restricted computer software' and use,
 duplication, and disclosure of the programs, including documentation,
 shall be subject to the restrictions in FAR 52.227-19, Commercial
 Computer Software-Restricted Rights (June 1987). Oracle Corporation,
 500 Oracle Parkway, Redwood City, CA 94065."

 End of Agreement
 You may terminate this Agreement by destroying all copies of the
 Programs. We have the right to terminate your right to use the
 Programs if you fail to comply with any of the terms of this
 Agreement, in which case you shall destroy all copies of the
 Programs.

 Relationship Between the Parties
 The relationship between you and us is that of
 licensee/licensor. Neither party will represent that it has any
 authority to assume or create any obligation, express or implied, on
 behalf of the other party, nor to represent the other party as agent,
 employee, franchisee, or in any other capacity. Nothing in this
 Agreement shall be construed to limit either party's right to
 independently develop or distribute software that is functionally
 similar to the other party's products, so long as proprietary
 information of the other party is not included in such software.

 Open Source
 "Open Source" software - software available without charge for use,
 modification and distribution - is often licensed under terms that
 require the user to make the user's modifications to the Open Source
 software or any software that the user 'combines' with the Open
 Source software freely available in source code form. If you use Open
 Source software in conjunction with the Programs, you must ensure
 that your use does not: (i) create, or purport to create, obligations
 of us with respect to the Oracle Programs; or (ii) grant, or purport
 to grant, to any third party any rights to or immunities under our
 intellectual property or proprietary rights in the Oracle
 Programs. For example, you may not develop a software program using
 an Oracle Program and an Open Source program where such use results
 in a program file(s) that contains code from both the Oracle Program
 and the Open Source program (including without limitation libraries)
 if the Open Source program is licensed under a license that requires
 any "modifications" be made freely available. You also may not
 combine the Oracle Program with programs licensed under the GNU
 General Public License ("GPL") in any manner that could cause, or
 could be interpreted or asserted to cause, the Oracle Program or any
 modifications thereto to become subject to the terms of the GPL.

 Entire Agreement
 You agree that this Agreement is the complete agreement for the
 Programs and licenses, and this Agreement supersedes all prior or
 contemporaneous Agreements or representations. If any term of this
 Agreement is found to be invalid or unenforceable, the remaining
 provisions will remain effective.

 Last updated: 01/24/08

 Should you have any questions concerning this License Agreement, or
 if you desire to contact Oracle for any reason, please write:
 Oracle America, Inc.
 500 Oracle Parkway,
 Redwood City, CA 94065

 Oracle may contact you to ask if you had a satisfactory experience
 installing and using this OTN software download.

Fichier sources/format

Il s'agit du fichier qui précise le type de paquet Debian. Dans notre cas, c'est un paquet natif.

3.0 (native)

Fichier oracle-instantclient/oracle-instantclient.conf

Il s'agit du fichier permettant au linker dynamique de trouver les bibliothèques partagées d'Oracle car elles ne sont pas situées dans /usr/lib.

Il doit être placé dans la racine du répertoire d'empaquetage (avant debian):

# Oracle Instant Client libraries
/usr/lib/oracle/11.2/client64/lib

Création du paquet

Nous allons utiliser dpkg-buildpackage pour créer le paquet:

$ cd ~/projects/oracle/packaging/oracle-instantclient
$ dpkg-buildpackage -b -us -uc

Voici l'explication des options:

  • -b indique que nous souhaitons créer uniquement le paquet binaire et non le paquet source.
  • -us indique que nous ne souhaitons pas signer le paquet source.
  • -uc indique que nous ne souhaitons pas signer le paquet .changes.

La construction du paquet devrait remonter quelques avertissements, notamment des symbôles non utilisés dans la bibliothèque libocci.so. Ce n'est pas grave, cela signifie que dpkg-shlibdeps n'a pas été capable de trouver ces symbôles dans d'autres bibliothèques pour déterminer les dépendances du paquet.

A l'issue de la création du paquet, vous devriez disposer du fichier ~/projects/oracle/packaging/oracle-instantclient_11.2.0.4.0-1_amd64.deb que vous pourrez installer via dpkg avec le compte root.

Paquet oracle-sqlplus-11.2.0.4-1.deb

Introduction

Le principe est le même que pour le paquet précédent. Je ne vais détailler que les fichiers qui changent.

Fichier control

Source: oracle-sqlplus
Section: non-free/database
Priority: extra
Maintainer: Médéric Ribreux <mederic.ribreux@medspx.fr>
Build-Depends: debhelper (>= 9.0.0~)
Standards-Version: 3.9.6

Package: oracle-sqlplus
Architecture: amd64
Depends: ${misc:Depends}, oracle-instantclient (=11.2.0.4.0-1)
Description: Oracle Instant Client SQLPlus utility
 Oracle SQLPlus is a command line sql utility. You can use it to send
 SQL commands and scripts to Oracle Database servers.
 

Fichier install

instantclient_11_2/sqlplus usr/lib/oracle/11.2/client64/bin
instantclient_11_2/libsqlplus.so usr/lib/oracle/11.2/client64/lib
instantclient_11_2/libsqlplusic.so usr/lib/oracle/11.2/client64/lib
instantclient_11_2/glogin.sql usr/lib/oracle/11.2/client64/lib

On place tout dans le même répertoire que pour le paquet précédent. Mais comme j'aime bien disposer de la commande sqlplus sans taper son chemin complet, nous allons créer un lien symbolique pour pallier à ce problème.

usr/lib/oracle/11.2/client64/bin/sqlplus usr/bin/sqlplus

Et voilà, sqlplus est disponible depuis le shell directement.

Fichier changelog

oracle-sqlplus (11.2.0.4.0-1) unstable; urgency=low

  * Initial release.

 -- Médéric Ribreux <mederic.ribreux@medspx.fr>  Sun, 24 May 2015 12:37:54 +0100

Fichier docs

instantclient_11_2/SQLPLUS_README

Création du paquet

On utilise également dpkg-buildpackage et on obtient

Paquet oracle-instantclient-dev-11.2.0.4-1.deb

Introduction

Même punition, il faut procéder de la même manière que pour le paquet oracle-instantclient, en supprimant le fichier links.

Fichier control

Source: oracle-instantclient-dev
Section: non-free/database
Priority: extra
Maintainer: Médéric Ribreux <mederic.ribreux@medspx.fr>
Build-Depends: debhelper (>= 9.0.0~)
Standards-Version: 3.9.6

Package: oracle-instantclient-dev
Architecture: amd64
Depends: ${misc:Depends}, oracle-instantclient (=11.2.0.4.0-1)
Description: Oracle Instant Client Development package
 This package allow development for third parties software based upon
 Oracle Instant Client. It provides the necessary headers to compile
 software that requires Oracle Database access.
 

Fichier changelog

oracle-instantclient-dev (11.2.0.4.0-1) unstable; urgency=low

  * Initial release.

 -- Médéric Ribreux <mederic.ribreux@medspx.fr>  Sun, 24 May 2015 12:37:54 +0100

Fichier install

instantclient_11_2/sdk/include/*.h usr/include/oracle/11.2/client64
instantclient_11_2/sdk/ottclasses.zip usr/lib/oracle/11.2/client64/lib
instantclient_11_2/sdk/demo/* usr/share/oracle/11.2/client64
instantclient_11_2/sdk/ott usr/share/oracle/11.2/client64

Fichier docs

instantclient_11_2/sdk/SDK_README

Fichier rules

#!/usr/bin/make -f

clean:
   dh_clean

%:
   dh $@

Placer le fichier tnsnames.ora

Nous disposons maintenant de paquets prêts à l'emploi mais il reste un dernier acte de configuration manuelle: le fichier tnsnames.ora. Difficile quand on conçoit un paquet de placer ce fichier. Faut-il le rendre disponible pour tout le système ou seulement pour l'utilisateur ?

Mon choix est cependant limité par le binaire fourni par Oracle. En effet, le client Oracle dans son ensemble (SQLPlus aussi) ne retrouve le fichier tnsnames.ora qu'en fonction d'une variable d'environnement (TNS_ADMIN ou ORACLE_HOME). Or, nous n'avons rien indiqué dans notre paquet pour créer ces variables d'environnement. De plus, je n'aime pas ajouter de nouvelles variables d'environnement pour tout le système.

Le système le plus simple et le plus propre que j'ai trouvé consiste à créer un répertoire .oracle dans votre répertoire home, à placer le fichier tnsnames.ora dedans et à définir la variable d'environnement TNS_ADMIN au niveau de votre ~/.profile. D'un côté, on permet à plusieurs utilisateurs différents de disposer de fichier tnsnames différents. De plus, par défaut, aucun utilisateur ne peut utiliser ce fichier sans action préalable ce qui me paraît plus intéressant d'un point de vue sécurité (ce n'est pas énorme mais c'est mieux que rien que d'empêcher un compte n'ayant pas forcément besoin du client Oracle de ne pas connaître les emplacements des serveurs de base de données).

Voici la manipulation:

$ mkdir ~/.oracle
$ mv tnsnames.ora ~/.oracle/
$ echo "# TNSNAMES for Oracle" >> ~/.profile
$ echo "export TNS_ADMIN=~/.oracle/" >> ~/.profile

Je l'ai indiquée dans le README.Debian du paquet oracle-instantclient.

Pourquoi .profile et non .bashrc. La réponse est assez simple: déclarer la variable dans .profile permet à tous les scripts non-interactifs qui sont lancés avec le shell sh de bénéficier de cette variable. C'est le cas du lanceur de QGIS par exemple. De plus, avec .profile, la variable est également disponible pour Bash. Que demande le peuple ?

Conclusion

Un simple:

# dpkg -i oracle-instantclient_11.2.0.4.0-1_amd64.deb oracle-instantclient-dev_11.2.0.4.0-1_amd64.deb oracle-sqlplus_11.2.0.4.0-1_amd64.deb

, suivi d'une initialisation de variable client (TNS_ADMIN), vous permettra d'installer le client Oracle, SQLPlus et le SDK sous forme de paquets Debian. C'est très pratique si vous devez installer ce client sur un grand nombre de serveurs par déploiement piloté (ou par des scripts).

Maintenant que nous avons les bases, il reste à voir comment créer les paquets Debian de QGIS en produisant le provider Oracle. Ce sera l'objet d'un prochain article...

Encore une fois, je ne suis pas un développeur Debian et ces paquets sont un peu spéciaux. J'ai sans doute fait des erreurs et peut-être que vous aurez besoin d'aller un peu plus loin. Dans ce cas, n'hésitez pas à lire la charte Debian et le guide du nouveau mainteneur Debian pour "hacker" plus loin !

Posted sam. 18 juil. 2015 14:27:57

Introduction

Parfois, vous n'aurez pas le choix. Comme bien souvent dans une entité, une DSI prend des décisions qui ne sont pas toujours les plus avisées et ce, pour de multiples raisons.

Ainsi, il est probable qu'on vous demande des choses complexes à réaliser. Dans ces éléments du quotidien, on va par exemple vous imposer de connecter un serveur sous Debian vers une base de données Oracle.

S'il avait fallu se connecter à un serveur PostgreSQL ou MySQL, l'opération aurait été sans doute beaucoup plus facile. Car, il faut bien l'avouer, demander de connecter un OS libre à des logiciels propriétaires est souvent synonyme de galère sans nom.

L'objet de cet article est de présenter une méthode pour régler ce problème de connexion. Il vous permettra d'installer le client Oracle sous Debian 8.0 (Jessie) ainsi que l'interpreteur SQL en ligne de commande d'Oracle. Nous verrons également comment connecter un client en Python via la bibliothèque cx_Oracle.

Rappel: Oracle Database est un logiciel propriétaire qui coûte assez cher. Le support des OS GNU/Linux est assuré uniquement pour la distribution RHEL et, bien entendu, la distribution Oracle Linux. Néanmoins, il est quand même possible d'installer le client Oracle officiel dans d'autres distributions, moyennant quelques manipulations assez simples à mettre en oeuvre.

Télécharger ce qu'il faut

Il vous faut:

Prenez soin de prendre la version adaptée à votre architecture. Dans la pratique, si vous êtes sous ARM, c'est mort ! Seules les architectures x86 et x86_64 sont gérées !

Bien sûr, comme Oracle est une entreprise, vous aurez besoin de créer un compte (à la con) pour seulement télécharger ces archives. Donnez une adresse email jetable, ça ne vaut pas la peine de rentrer dans ce jeu (après tout, vous utilisez Oracle parce qu'on vous oblige à le faire) !

Installer l'ensemble

Voici mon approche:

  • J'installe tout dans /opt/oracle, conformément aux règles FHS.
  • Il faudra ensuite modifier quelques variables d'environnement pour accéder à ce répertoire.
# apt install libaio1
# mkdir -p /opt/oracle
# cd /opt/oracle
# unzip /tmp/instantclient-basic-linux.x64-12.1.0.2.0.zipunzip /tmp/instantclient-basic-linux.x64-12.1.0.2.0.zip
# unzip /tmp/instantclient-sdk-linux.x64-12.1.0.2.0.zip
# unzip /tmp/instantclient-sqlplus-linux.x64-12.1.0.2.0.zip
# cd instantclient_12_1 && ln -s libclntsh.so.12.1 libclntsh.so

Ensuite, il reste à déclarer quelques variables d'environnement pour que tout fonctionne correctement

$ export ORACLE_HOME=/opt/oracle/instantclient_12_1
$ export LD_LIBRAY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME
$ export PATH=$PATH:$ORACLE_HOME

Copiez ça dans votre .bashrc !

# Oracle things
export ORACLE_HOME=/opt/oracle/instantclient_12_1
if [ "$LD_LIBRARY_PATH" = "" ]; then
    export LD_LIBRARY_PATH=$ORACLE_HOME
else
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME
fi
export PATH=$PATH:$ORACLE_HOME

Si vous avez un fichier tnsnames.ora, le fichier qui référence les connexions vers le ou les serveurs Oracle de votre environnement, vous devez le placer au bon endroit (celui par défaut), ce qui vous permettra d'économiser une variable d'environnement.

# mkdir -p /opt/oracle/instantclient_12_1/network/admin
# cp /tmp/tnsnames.ora /opt/oracle/instantclient_12_1/network/admin/

Tester que tout marche

Le client est installé et configuré, il reste à tester l'ensemble. Vous devez disposer d'un vrai serveur Oracle Database pour vérifier que la connexion se déroule correctement. Pour réaliser ce test de connexion, nous allons utiliser SQLPlus (après tout, c'est le client officiel):

$ sqlplus user/password@tnsname
                                                                            
SQL*Plus: Release 12.1.0.2.0 Production on Tue Jul 21 14:33:08 2015

Copyright (c) 1982, 2014, Oracle.  All rights reserved.


Connecte a :
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

SQL>

Si vous avez le prompt SQL, alors ça veut dire que votre installation est fonctionnelle. Si ce n'est pas le cas, veillez à bien spécifier le tnsname tel qu'il est indiqué dans le fichier tnsnames.ora. Par exemple dans:

THESERVER.WORLD =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = sdf.my-domain.example)(PORT = 51478))
    (CONNECT_DATA = (SID = theserver))
  )

Le nom du tnsname est bien THESERVER.WORLD et non theserver qui correspond au SID. Le SID (Oracle System Identifier) était utilisé pour les serveurs Oracle Database d'avant la version 8.1.

Par ailleurs, le client Oracle gère le fichier tnsnames.ora de façon équivalente s'il est encodé avec des caractères de fin de ligne de MS-Windows. Vous pouvez le copier tel quel sur votre Debian et ça devrait fonctionner.

Installer cx_Oracle

Maintenant que nous disposons de tout ce qu'il faut comme binaire pour Oracle, on peut lancer la création de cx_Oracle. Je vous recommande de télécharger la source dans un répertoire puis de le compiler via les instructions standard. En effet, sous Debian, l'utilisation des distutils permet de créer les modules Python dans /usr/local/lib/python2.7/dist-packages/.

Attention, par défaut, Debian Jessie utilise Python 2.7 !

# apt install python-dev build-essential
$ cd ~/projects/oracle/
$ wget https://pypi.python.org/packages/source/c/cx_Oracle/cx_Oracle-5.1.3.tar.gz
$ tar -xzf cx_Oracle-5.1.3.tar.gz
$ cd cx_Oracle-5.1.3
$ python setup.py build
# python setup.py install

Ensuite, un simple chargement du module cx_Oracle sous Python devrait vous confirmer que tout est correct. Si vous voulez vraiment tester une connexion vers un serveur existant, adaptez le script qui suit devrait suffire:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import cx_Oracle

connection = cx_Oracle.Connection("user/password@tnsname")
cursor = connection.cursor()

try:
    cursor.execute("select 1 / 0 from dual")
except cx_Oracle.DatabaseError, exc:
    error, = exc.args
    print >> sys.stderr, "Oracle-Error-Code:", error.code
    print >> sys.stderr, "Oracle-Error-Message:", error.message

Conclusion

Ce document permet d'installer le client Oracle 12c sous Debian Jessie amd_64. C'est assez facile finalement et on peut facilement créer des scripts de déploiement (Puppet/Ansible et autres) ! Avec cx_Oracle, Oracle Database est également accessible à tout bon codeur Python tout en bénéficiant de l'API DB 2.0 de ce dernier, vous permettant de créer du code (quasi) indépendant du SGBDR.

Mais il faut quand même relativiser: l'installation du dernier client PostgreSQL et de la bibliothèque Python relative se réalise de la manière suivante:

# aptitude install postgresql-client python-psycopg2

C'est quand même bien plus facile, non ?

A la fin de cet article, il reste un point intéressant à étudier. En effet, si vous êtes sous Debian, pourquoi ne pas créer un ensemble de paquets permettant de déployer ces binaires grâce à dpkg (et le reste des outils permettant d'installer des paquest Debian) ? Ce sera l'objet d'un prochain article...

Posted mar. 14 juil. 2015 17:24:15

Introduction

Je gère de plus en plus de choses sous Git: mon blog, mes exemples de code, mes configurations, mes projets de développement, etc. A la longue, on finit par avoir de nombreux projets et il devient presque indispensable de pouvoir disposer d'une interface pour mieux les gérer, les consulter, les évaluer. Mon travail avec QGIS m'amène souvent à utiliser l'interface de GitHub pour consulter le code source du projet lorsque je remonte des bugs. De fait, j'ai trouvé que c'était assez intéressant de pouvoir naviguer rapidement dans le code, directement depuis son navigateur web, en quelques clics.

En effet, si je prends l'exemple de QGIS, cloner le dépôt revient à télécharger près de 1Go de données. Quand c'est juste pour faire un grep pour trouver une variable ou une méthode, ça fait cher de la recherche ! Par ailleurs, un dépôt Git de code a une vie bien à lui. Par exemple, certains dépôts sont très actifs pendant une période donnée et après, parce que le projet est abouti, le dépôt devient une archive. Sur ce cas particulier, on peut penser que le dépôt ne sera plus cloné ailleurs que sur le serveur lui-même et, si on a besoin de consulter le code, il faudra à nouveau le cloner, le consulter, faire des recherches, etc... Bref, se replonger dans le code. Avec le temps, vous aurez sans doute également oublié l'URL qui permet de cloner le dépôt.

C'est là qu'une interface web qui vous permet de naviguer de manière centralisée dans vos dépôts se révèle être un grand atout. Vous avez une seule URL à retenir pour accéder au résumé de vos projets. Si vous n'êtes pas chez vous, vous pouvez cloner facilement vos dépôts, soit à l'aide de Git soit en téléchargeant une archive. Vous avez accès à l'historique de votre développement ce qui vous permet de retrouver facilement ce que vous avez mis en place précédemment. Enfin, comme sous GitHub ou GitLab, vous pouvez lire le code source directement ce qui est une fonctionnalité très pratique au quotidien, notamment pour la revue de bogues.

Les plateformes GitHub, BitBucket, GitLab et consors présentent ces fonctionnalités depuis leurs débuts. Mais comme vous le savez si vous lisez ce blog, je pense qu'il est important de décentraliser le maximum de ressources sur Internet. Dans cet objectif, je vous propose de mettre en place une solution de consultation de dépôts Git que vous pourrez administrer par vos propres soins, de manière complètement autonome et indépendante des silos habituels...

Besoins et réponse

Il est temps de reprendre et de lister ce dont nous avons besoin:

  • Il nous faut un navigateur "Web" de dépôts Git.
  • Cette interface de navigation doit être un logiciel libre.
  • Cette interface sera disponible uniquement via HTTPS.
  • Elle imposera une authentification HTTP.
  • La gestion de droits sera triviale: celui qui peut accéder à l'interface aura un accès complet à l'interface.
  • L'interface doit être capable de gérer automatiquement tout nouveau projet (il ne faut PAS devoir modifier la configuration de l'interface).
  • Le programme de l'interface doit être rapide et léger. Il est destiné à tourner sur un plugcomputer, une machine qui possède à peu près les caractéristiques techniques des serveurs d'il y a 15 ans !
  • Si possible, l'interface ne doit pas imposer l'installation d'un framework lourd (JAVA/Ruby/Qt/Gtk/etc. excluded !).
  • L'interface doit permettre de consulter le source des projets.
  • L'interface doit offrir une visualisation des différents commits.
  • Il faudra pouvoir télécharger des archives de code depuis l'interface.

La réponse se trouve sous la forme d'un excellent programme nommé CGit. Il est écrit en C et se propose d'être une interface très (hyper) rapide de consultation de dépôts Git. Il se présente sous la forme d'un binaire CGI qui génère des pages Web en se basant sur le contenu d'un fichier de configuration et surtout du contenu de vos dépôts Git.

Attaquons maintenant sa mise en place et sa configuration.

Installation de cgit

Si vous êtes sous Debian Jessie (version dans laquelle vous DEVRIEZ être depuis le mois de mai 2015), un simple

# apt install cgit

devrait suffire.

Un rapide coup d'oeil au paquet permet de voir que l'implémentation de CGit est très simple. En effet, l'essentiel du programme est concentré dans le fichier binaire /usr/lib/cgit/cgit.cgi qui fait tout le travail. Le paquet Debian livre un fichier de configuration de base (/etc/cgitrc) ainsi qu'une configuration pour Apache v2.4 (/etc/apache2/conf-available/cgit.conf). Enfin, quelques scripts de filtre sont disponibles dans /usr/lib/cgit/filters. Ces derniers permettent de customiser la mise en forme des rendus des pages d'information, des adresses de courrier électronique ainsi que de la visualisation des codes sources.

Note: Pour les personnes qui sont encore sous Debian Wheezy, vous pouvez installer le paquet cgit sans aucun problème si vous disposez d'une machine sous l'architecture armel. C'est le cas des Sheevaplugs par exemple. En effet, le paquet Debian disponible sous Debian Jessie ne nécéssite que la version 2.7 de la libc sous armel alors qu'il nécéssite la version 2.14 de la libc dans les autres architectures. Sous Debian Wheezy, la libc est en version 2.13 ce qui est amplement suffisant pour faire tourner le binaire.

Pour information, la configuration d'Apache (v2.4) sous Debian Jessie qui est livrée par défaut pour cgit ne me convient pas. Il faut donc la modifier pour prendre en compte nos besoins, notamment sur la partie authentification. Pour ma part, je souhaite que l'interface soit disponible sur le virtualHost principal sous l'URL /cgit/ uniquement sur un canal chiffré par TLS. De plus, je ne souhaite pas que le dépôt soit public. Je souhaite utiliser l'authentification HTTP d'Apache pour définir qui a droit ou non d'accéder au dépôt. Voici ce que j'ai ajouté à mon fichier de configuration de site dédié au HTTPS /etc/apache2/sites-available/medspx.fr.tls:

ScriptAlias /cgit/ "/usr/lib/cgit/cgit.cgi/"
RedirectMatch ^/cgit$ /cgit/
Alias /cgit-css "/usr/share/cgit/"
<Directory "/usr/lib/cgit/">
   AllowOverride None
   Options ExecCGI FollowSymlinks
   AuthType Basic
   AuthName "CGit authentication"
   AuthUserFile /etc/apache2/webdav-users
   Require valid-user
</Directory>

Ensuite, la configuration d'Apache est classique. Il faut juste prendre le temps de supprimer la configuration de cgit qui s'enclenche par défaut lors de l'installation du paquet:

# a2disconf cgit
# systemctl restart apache2

Configuration générale de cgit

Cgit concentre sa configuration dans un seul fichier texte: /etc/cgitrc. La syntaxe de ce dernier est assez simple à comprendre. Je vous invite à lire la page de manuel de cgitrc (man cgitrc) qui est très bien faite. Elle décrit l'ensemble des options disponibles.

Voici mon fichier de configuration commenté:

# cgit config
# see cgitrc(5) for details

# Un peu de cosmétique
css=/cgit-css/cgit.css
logo=/favicon.ico
favicon=/favicon.ico

# Customisation de la page d'accueil
root-title=Medspx Git repositories
root-desc=Git repositories navigation
root-readme=/etc/cgit-about.md

# Configuration d'options de base
enable-index-links=1
enable-commit-graph=1
enable-log-filecount=1
enable-log-linecount=1
side-by-side-diffs=1

# Je ne souhaite pas que les robots puissent indexer ce dépôt
robots=noindex, nofollow

# Ici, je veux indiquer une URL pour cloner le dépôt
clone-url=https://$HTTP_HOST/git/$CGIT_REPO_URL

# cgit peut générer des archives à télécharger suivant vos tags
snapshots=tar.gz tar.bz2 zip

# Coloration syntaxique des page A propos et du visualisateur de fichiers
source-filter=/usr/lib/cgit/filters/syntax-highlighting.py
about-filter=/usr/lib/cgit/filters/about-formatting.sh

# La taille des binaires affichés dans le visualisateur est limitée à 200 Ko
max-blob-size=200

# Gestion des mimetypes
mimetype-file=/etc/mime.types

# Les fichiers readme par défaut auront les noms qui suivent
readme=:README.md
readme=:readme.md

# Les dépôts git peuvent implémenter leurs propres filtres
enable-filter-overrides=1

# L'endroit où trouver les dépôts git (le truc le plus important)
scan-path=/var/local/git

Je n'ai pas positionné les directives liées à la gestion du cache de CGit. En effet, mon site web a un traffic très faible et j'ai d'abord créé le dépôt Git pour moi-même. Les besoins sont donc d'un niveau de performance assez restreint. Je peux donc me permettre de conserver la configuration par défaut du cache de CGit qui suffit très largement. N'oubliez pas de remplir le fichier /etc/cgit-about.md avec un descriptif de votre site, ce sera mieux pour l'affichage.

A ce stade, vous disposez d'une interface Web disponible sur votre serveur HTTP à l'URL /cgit/. Si vous avez des dépôts Git dans le répertoire /var/local/git, CGit vous les affichera et vous pourrez commencer à naviguer dedans. Vous pourrez lire le code, visualiser les diffs entre deux commits, voir l'historique du projet, etc. Autre élément d'intérêt, sachez que lorsque la directive snapshots est activée, vous pourrez télécharger une archive depuis chaque commit de votre projet. Si vous avez utilisé des tags, vous pourrez télécharger chaque archive selon vos tags directement depuis la page d'accueil du dépôt. C'est CGit qui génère l'archive et qui la place dans son cache. Pas besoin de gérer ces éléments à la main et c'est tant mieux !

Néanmoins, il manque pas mal de choses sur vos dépôts, le plus frappant étant l'absence de description de chaque dépôt ainsi que les noms bruts des répertoires hébergeants les dépôts. Voyons comment y remédier...

Gérer la configuration de cgit pour chaque dépôt

En règle générale, pour ce qui concerne l'administration système, j'aime les choses statiques. On configure un élément une bonne fois pour toute et après, la configuration est statique et quasiment immuable dans le temps. Donc, sur un serveur en production, tout changement intempestif de ce qui se trouve dans /etc est à éviter (en dehors des évolutions de système). Dans notre cas, le contenu des dépôts Git va évoluer. CGit présente des éléments du projet comme une description, un fichier readme ou about, des commentaires, des statistiques basiques, etc. Or, bien souvent, au cours du projet, ces éléments peuvent varier. Par exemple vous voulez sans doute changer le nom d'un dépôt ou sa description détaillée. Ou alors, un développeur utilise le fichier readme.md pour autre chose que la présentation succincte du projet (ou bien le nom de ce fichier a tout bonnement changé dans le dépôt).

Dans ces situations, il faudra modifier la configuration du dépôt dans cgit. Par défaut, vous devrez donc aller modifier à la main le fichier /etc/cgitrc situé sur le serveur hébergeant le service. Je trouve cette pratique assez fastidieuse. Essayons de trouver un moyen un peu différent pour nous permettre de parvenir à rendre tout ça plus automatique et modulable.

En lisant la documentation de cgit, on se rend compte que la directive enable-git-config permet de mettre les éléments de paramétrage de chaque dépôt dans la configuration de chaque dépôt (le répertoire .git). Voilà qui est déjà mieux... mais pas suffisant ! En effet, la configuration Git du dépôt n'est pas un objet de la base Git. Ainsi, si vous avez réalisé une configuration sur votre clone, elle ne pourra pas atteindre le répertoire .git du dépôt sur le serveur. Par ailleurs, il faut savoir que par défaut, CGit scanne chaque dépôt à la recherche d'un fichier cgitrc qui contient les éléments de configuration du dépôt.

Après de nombreux tests et surtout, une bonne lecture du source de CGit, je me suis rendu compte que ce fichier cgitrc ne peut pas être stocké dans le dépôt. En effet, CGit recherche le fichier dans le répertoire .git. Mais Git est très modulable, notamment avec ses hooks. J'ai donc eu l'idée de permettre de recopier le fichier cgitrc du dépôt dans le répertoire .git afin que CGit puisse en faire bon usage. Voici donc le source du hook post-update qui se déclenche sur le serveur Git une fois l'ensemble des modifications répercutées sur la copie locale du serveur:

#!/bin/sh

# Hook script to copy cgitrc file into the .git directory

CGITCONFIG=$(git ls-tree --name-only master .cgitrc)
if [ "$CGITCONFIG" = ".cgitrc" ]; then
    echo "Copying cgitrc into .git directory..."
    git archive master --format=tar .cgitrc | /bin/tar -x -C $GIT_DIR
    if [ -e "$GIT_DIR/.cgitrc" ]; then
        mv $GIT_DIR/.cgitrc $GIT_DIR/cgitrc
    fi
fi

exit 0

Voici un exemple de configuration d'un fichier cgitrc d'un dépôt:

name=org
desc=My life in Org-Mode
section=Publications
readme=:readme.md
owner=Médéric Ribreux <mederic.ribreux@medspx.fr>

Bien entendu, avec cette méthode, il faut copier le hook dans chaque répertoire .git/hooks de chaque projet. Mais, dans mon cas, l'initialisation d'un dépôt Git même vide implique de se connecter vis SSH et de jouer du shell directement sur le serveur. Je n'ai en effet pas automatisé ce processus pour des questions de simplicité. Néanmoins, j'applique une procédure manuelle assez simple à suivre. Pour éviter d'oublier ce hook, une méthode assez simple consiste à l'installer dans le répertoire de template par défaut. Sous Debian, il s'agit de /usr/lib/git-core/templates/'. Pour une plus grande personnalisation, nous allons créer un répertoire dédié dans/usr/local/`. Puis nous allons y mettre nos templates et enfin, nous allons configurer git pour qu'il utilise ce répertoire par défaut.

# mkdir -p /usr/local/share/git-core/templates/
# cp -r /usr/share/git-core/templates/* /usr/local/share/git-core/templates/
# cp /home/user/post-update /usr/local/share/git-core/templates/hooks/
# chmod 755 /usr/local/share/git-core/templates/hooks/post-update
# git config --system init.templatedir /usr/local/share/git-core/templates

Pour profiter de notre hook, il suffit de créer un fichier .cgitrc à la racine du projet et de faire un commit suivi d'un push !

Une dernière précision ! Vous devez vous assurer que les permissions dans le dépôt Git soient suffisantes pour que l'utilisateur qui va effectuer les opérations via git-http-backend (souvent www-data sous Debian) puisse écrire le fichier au bon endroit. A vos chmod !

Conclusion

CGit est assez intéressant dans son approche. Il est très léger et très performant. De plus, ses fonctionnalités le rendent très intéressant pour les personnes qui ont des besoins assez simples dans la gestion de leurs dépôts Git. Les développeurs confirmés, travaillant avec une communauté de développement étoffée, auront sans doute des besoins plus rigoureux en termes de sécurité et de fonctionnalités de partage.

Par ailleurs, je n'ai pas abordé la gestion des droits en profondeur car cgit n'offre que très peu d'éléments dessus mais il est tout à fait possible de combiner cgit avec un système de gestion de droits comme gitolite par exemple.

Pour ma part, CGit est également un logiciel intéressant de par lui-même. D'abord, il est écrit en C, ce qui, en dehors des logiciels du type outils de traitement bruts ou noyau est rare. De plus, je n'ai pas souvenir d'avoir déjà rencontré un logiciel qui produit du HTML codé en pur C. Ensuite, il reste très performant et finalement assez facile à configurer. CGit est la preuve qu'il est possible combiner développement pointu en C et monde du Web. C'est quelquechose que je souhaiterais avoir plus souvent car cette proposition permet d'utiliser de petites configurations (tant qu'on reste dans des limites correctes) et profiter de fonctionnalités quand même avancées.

Comme point de comparaison, on peut prendre GitLab qui tient une liste de pré-requis techniques sur son site Web. On peut y lire qu'il faut quand même beaucoup de choses pour le faire tourner à minima, notamment Ruby (qui reste assez gourmand sur un plugcomputer) et qu'il faut au moins 1 coeur de CPU pour faire tourner moins de 100 utilisateurs; enfin, 512Mo de RAM est un minimum. Le ticket d'entrée de GitLab est clairement au dessus de ce que peut fournir une petite machine ARM. Certes les fonctionnalités de GitLab sont largement supérieures à celles de CGit mais comme qui peut le plus peut le moins, l'utilisateur qui voudrait utiliser uniquement les fonctions basiques de GitLab serait obligé de disposer d'une puissance que ne pourrait lui fournir un Raspberry Pi 2 par exemple.

A l'inverse, pour le développeur autonome, CGit permet de commencer à mettre quelquechose en place avec sans doute moins de tâches d'administration système (ce simple article en est l'illustration pratique).

Pour terminer, un grand nombre de développeurs Debian utilisent CGit pour leur convenance personnelle (Lars Wizenius par exemple) ou directement dans l'infrastructure de Debian.

Posted ven. 15 mai 2015 19:49:00

Introduction

En ce moment, je consumme mes heures de loisirs dans un jeu vidéo qui a pratiquement 10 ans. Il s'agit d'Oblivion, quatrième volet de la saga des Elders Scrolls. Outre l'intérêt du jeu, j'ai choisi délibérément de l'utiliser uniquement sous Debian. D'ailleurs, je n'ai pas de multiboot sur ma machine principale. Mais en 2015, force est de constater que Wine, le lanceur natif d'applications MS-Windows pour GNU/Linux, s'est considérablement amélioré. Je peux donc utiliser Oblivion directement sous Debian via Wine. Voici quelques détails sur ma configuration.

Configuration de Wine

Il faut commencer avec une configuration correcte de wine, notamment au niveau des lecteurs utilisés. Wine ayant tendance à tout fourrer dans ~/.wine/dosdevices, j'ai vite créé un lien symbolique vers un emplacement dédié (dans /media/data/gamez/Wine/drive_c) pour ne pas exploser la taille de mon répertoire home. Par ailleurs, il faut indiquer que le lecteur CD sera disponible sur un point de montage correct (/media/cdrom0 pour ma part).

On peut modifier ces emplacements avec l'utilitaire winecfg, dans l'onglet Lecteurs.

Installation

La première chose à faire est de copier l'image ISO du DVD. Pour cela, une simple commande de dd suffit:

$ dd if=/dev/dvd of=/media/data/games/Oblivion/oblivion.iso bs=1M

Une fois l'image iso capturée, il reste à la monter (vous savez faire) et à effectuer l'installation via wine (via wine setup.exe). Et c'est tout !

Configuration d'Oblivion

Le jeu stocke les données de configuration et les sauvegardes dans le répertoire équivalent MS-Windows: C:\USERS\$USER\Mes Documents\My Games\Oblivion\. Il faut savoir que par défaut, Wine créé un lien symbolique de tout ce qui concerne les répertoires Ma Musique, Mes Documents, Mes Vidéos, etc. vers le répertoire home (le vrai, celui du vrai OS) de l'utilisateur. Pour ma part, cela abouti à placer My Games\Oblivion dans ~/My Games/Oblivion.

Par défaut, Oblivion affiche les crédits et une vidéo de lancement et ce, à chaque démarrage. La première fois, c'est intéressant mais au bout de trois fois, on en a facilement marre. La solution consiste à modifier le fichier INI du jeu pour éviter ces lancements. Il s'agit du fichier Oblivion.ini situé dans le répertoire sus-nommé. La variable SIntroSequence permet d'indiquer ce qui sera utilisé comme séquence d'introduction. Il suffit de ne rien mettre dans cette variable pour annuler la séquence d'introduction. C'est la même chose pour les variables SMainMenuMovie et SMainMenuMovieIntro.

SIntroSequence=
SMainMenuMovieIntro=
SMainMenuMovie=

Script de lancement

Pour les jeux qui fonctionnent sous Wine (et il y en a un paquet), je créé un script de lancement dédié que je place dans ~/bin. Cela permet de lancer le jeu en une seule commande. Par ailleurs, la logique de lancement est souvent la même:

  • Vérifier si l'image ISO du DVD est lancée.
  • La monter
  • Se placer dans le bon répertoire
  • lancer wine
  • à la fin du jeu, démonter l'image DVD.

Pour Oblivion, j'avais un autre problème à gérer: la configuration des touches. Par défaut, je devais toujours reconfigurer la touche 'Z' et la touche 'Q' pour respectivement avancer et aller à gauche. En fait, on peut facilement corriger ce problème en indiquant au serveur X qu'on va utiliser un clavier US (via setxkbmap).

Voici donc le script qui fait le travail de lancement de l'application:

#!/bin/bash

# Script de Lancement d'Oblivion sous Wine

## On monte le DVD
fusermount -u /media/cdrom0
fuseiso /media/data/gamez/Oblivion/oblivion.iso /media/cdrom0

## On met le clavier en US pour que le jeu fonctionne correctement
setxkbmap us

## On lance Oblivion avec Wine depuis le bon répertoire
cd /media/data/gamez/Wine/drive_c/Oblivion
wine ./Oblivion.exe

## on remet le clavier dans le bon format
setxkbmap fr latin9

## On démonte le DVD
fusermount -u /media/cdrom0
cd ~
exit 0

Conclusion

Il est plaisant de voir qu'en 2015, on peut jouer de manière fluide directement sous Wine à des jeux AAA d'il y a un peu moins de 10 ans. Par ailleurs, le jeu est vraiment très bon. J'en suis à plus de 70 heures et je suis loin d'être au bout. Je ne connaissais pas vraiment la série des Elders Scrolls mais le principe est assez intéressant: on incarne un personnage assez libre d'évoluer comme bon lui semble dans un monde assez élaboré. Les quêtes sont très nombreuses et très variées et on n'a pas vraiment le temps de s'ennuyer. Peut-être un bon tremplin vers Skyrim ?

Posted sam. 18 avril 2015 11:25:05

Introduction

Parfois, on n'a pas le choix, le port SSH est définitivement inaccessible depuis l'extérieur. Dans les entreprises, la politique de pare-feux vient souvent fermer tous les ports différents de 80 et de 443 et un serveur mandataire vient encore un peu plus surveiller les échanges. Dans ces conditions, il serait intéressant de pouvoir disposer d'un logiciel qui permette un accès Shell via un simple navigateur web.

Au delà des accès fermés des entreprises, il arrive parfois qu'on ne dispose pas d'un client distant. Par exemple, si vous êtes sur une machine bien verrouillée ou si vous utilisez une machine d'emprunt qui tourne sous un système d'exploitation dénué d'un client SSH. Dans ces conditions, un accès shell via le Web serait d'un grand intérêt même si d'un point de vue sécurité, on a vu mieux (notamment si la machine sans SSH dispose d'un keylogger).

Ce petit article a pour objet de faire une petite revue des différents terminaux SSH libres en évaluant rapidement leurs fonctionnalités ainsi que leur mode d'installation.

Présentations

J'ai retenu trois logiciels de terminaux web pour fonctionner

J'ai rapidement exclu Ajaxterm essentiellement pour des raisons esthétiques: dans mon navigateur en mode tuilé, il semble que l'affichage du shell ne se passe pas correctement. Je ne pouvais pas afficher une fenêtre de terminal lisible même en essayant de modifier les paramètres de taille du terminal. Étant dans une impasse, je n'ai pas pu en tester les fonctionnalités.

Avec Shellinabox, je n'ai pas eu ces problèmes et j'ai rapidement pu me lancer à faire des tests. Ce dernier est codé en C et il semble très rapide. De son côté, Gate One est codé en Python et il dispose d'une sérieuse page de présentation. Reste à tester tout ça !

Shellinabox

Installation et configuration

aptitude install shellinabox

Suffit pour installer shellinabox et le faire tourner avec une configuration de base. Cette dernière installe le service sur le port 4200 sur toutes les interfaces réseaux. Vous pouvez y jeter un oeil en allant sur https://localhost:4200.

Par défaut, shellinabox utilise un utilisateur dédié (et non avec les pouvoirs de root) ce qui est plutôt intéressant en matière de privilèges. Mais d'un point de vue de sécurité, on peut aller plus loin. Notamment, n'oublions pas que shellinabox écoute par défaut sur toutes les interfaces réseaux et que, par conséquence, tout Internet peut s'y connecter. Il faut donc modifier un peu les options de démarrage pour pouvoir obtenir ce qu'on veut. La configuration de shellinabox se fait essentiellement dans /etc/default/shellinabox. Le répertoire /etc/shellinabox se comporte de la même manière que celui d'Apache2. On trouve en effet un ensemble de fichiers css dans le répertoire options-available qu'on active en créant des liens symboliques dans le répertoire options-enabled.

Avant toute chose, voici ce que je souhaite pour mon installation de shellinabox:

  • Je souhaite y accéder via une URL du type https://my.server.example.com/terminal .
  • L'accès sera uniquement sur un canal chiffré par TLS.
  • L'accès à la page sera soumise à un authentification HTTP en mode Basic (étant donné qu'on utilise TLS).
  • Le tout sera servi par un serveur web déjà existant (Apache2).

Voici les options que j'ai retenue pour Shellinabox dans cette configuration:

  • Par défaut, il ne faut écouter que sur localhost. Pas besoin d'un trou de sécurité supplémentaire. C'est l'option --localhost-only.
  • Pas besoin de travailler en mode chiffré, c'est Apache qui va gérer TLS. C'est l'option --disable-ssl.
  • Je veux un port différent de celui par défaut, genre 34200. C'est l'option SHELLINABOX_PORT

A la fin, voici mon fichier /etc/default/shellinabox

# Should shellinaboxd start automatically
SHELLINABOX_DAEMON_START=1

# TCP port that shellinboxd's webserver listens on
SHELLINABOX_PORT=34200

# Parameters that are managed by the system and usually should not need
# changing:
# SHELLINABOX_DATADIR=/var/lib/shellinabox
# SHELLINABOX_USER=shellinabox
# SHELLINABOX_GROUP=shellinabox

# Any optional arguments (e.g. extra service definitions).  Make sure
# that that argument is quoted.
#
#   Beeps are disabled because of reports of the VLC plugin crashing
#   Firefox on Linux/x86_64.
SHELLINABOX_ARGS="--no-beep --localhost-only --disable-ssl"

Attaquons-nous maintenant à la configuration d'Apache2. Je souhaite accéder par TLS à une page web dont l'accès est protégé par une authentification Basic qui redirige vers Shellinabox. Cette redirection sera gérée par les fonctionnalités de ReverseProxy d'Apache. Pour la partie TLS, je dispose déjà d'un service fonctionnel. Au pire, vous pouvez toujours activer le site TLS par défaut d'Apache (a2ensite default-ssl).

D'abord, il faut activer les modules mod_proxy et mod_proxy_http. Ces derniers vont permettre d'ajouter les fonctionnalités de Proxy et de ReverseProxy pour Apache:

# a2enmod proxy
# a2enmod proxy_http

Ensuite, on peut simplement activer les fonctionnalités de ReverseProxy avec deux directives Apache que vous pouvez placer dans le VirtualHost par défaut:

# ShellInaBox
## On désactive les fonctions de Proxy direct
ProxyRequests Off
## On active les fonctions de Mandataire inverse
ProxyPass /terminal http://localhost:34200
ProxyPassReverse /terminal http://localhost:34200

ProxRequests est une directive Apache utilisée pour configurer l'accès mandataire direct. Ce n'est pas celui qui nous intéresse donc nous forçons la configuration à Off pour être sur qu'elle soit désactivée. Viennent ensuite les directives ProxyPass et ProxyPassReverse. ProxyPass monte un reverse proxy pour l'url /terminal et exécute la requête sur localhost:34200 qui est notre serveur shellinabox. ProxyPassReverse gère les éventuelles redirections d'URL que shellinabox pourrait lancer. A priori, ce ne sera jamais le cas mais comme ça ne coûte rien, autant renseigner cette directive.

Il nous reste maintenant à gérer l'authentification. Voici l'ensemble de directives commentées pour mieux comprendre:

# Configuration ShellInaBox
## On désactive les fonctions de Proxy direct
ProxyRequests Off
## Shellinabox sera disponible à l'emplacement /terminal
<Location /terminal>
  ## On active les fonctions de Mandataire inverse
  ProxyPass http://localhost:34200
  ProxyPassReverse http://localhost:34200
  ## On donne l'accès à cet emplacement à tout Internet
  Order allow,deny
  Allow from all
  ## On restreint l'accès à un utilisateur dédié
  AuthName "Acces Shellinabox"
  AuthType Basic
  AuthUserFile /etc/apache2/shellinabox_passwd
  Require user shellinabox_admin
</Location>

Bien entendu, il faut créer un fichier de mot de passe avec au moins un compte dedans (le compte d'accès à shellinabox):

htpasswd -c shellinabox_passwd shellinabox_admin

Voilà un exemple de sécurisation de shellinabox. De cette manière, on peut exposer ce service à Internet, la couche de protection étant apportée par Apache grâce à l'authentification. Toutefois, vous veillerez à mettre en place une directive fail2ban sur ce point pour éviter les attaques en force brute. Il existe des centaines de manière de sécuriser l'accès à ShellInabox via Apache. Cette implémentation est un moyen simple d'y parvenir, dans un contexte avec peu d'utilisateurs.

Évaluation

Une fois installé, il convient de tester la bête. Je vais vite faire le tour car ses fonctionnalités sont assez limitées. D'ailleurs, c'est bien le but: on veut un terminal pour administrer, c'est tout !

Vous pouvez modifier le style du terminal en activant le menu utilisateur de ShellInabox en faisant un clic droit dans la fenêtre. Mon test de base s'est contenté de lancer des commandes shell et de constater que la réponse est assez rapide même sur un équipement limité.

J'ai essayé d'utiliser Emacs et j'ai été plutôt surpris par la réactivité, à condition que vous utilisiez le style monochrome sinon l'affichage est ultra-lent. J'ai également testé Mutt et tout s'est très bien passé.

Petit inconvénient, sur les claviers AZERTY, il semble que certaines touches ne passent pas, notamment les touches $/*ù). Le bug est référencé chez Debian. Cela peut être vite génant dans l'expérience utilisateur, notamment si vous comptez abuser de cet accès au shell de votre serveur. Un moyen de contournement consiste à faire un clic-droit dans le terminal et de choisir l'outil "paste from browser". On peut alors écrire ce qu'on veut avec.

Par ailleurs, shellinabox détecte les URL http et permet de les ouvrir directement dans le navigateur Web.

Pour tester les performances, j'ai effectué le "test de la racine": ça consiste à faire un ls -R / et à voir comment se comporte l'affichage en surveillant les processus. Le retour que j'ai de ce test c'est que le processus shellinaboxd reste peu gourmand, il monte peu dans les tours de CPU. En revanche, c'est le navigateur web qui a plus de mal: il peut consommer 100% de CPU (test réalisé avec iceweasel 25). Mais ce constat me va bien: le serveur que je souhaite administrer à distance n'aura pas à pâtir de l'utilisation de Shellinabox et mon navigateur web peut bien attendre un peu !

Gate One

Installation et configuration

Gate One est un autre terminal Web. Ses sources sont disponibles sur Github et il est possible d'acheter des paquets d'installation ou de payer des licences pro. De mon côté, je vais juste partir des sources pour "compiler" (c'est du Python). Pour cela, vous aurez besoin du paquet python-stdeb.

$ git clone https://github.com/liftoff/GateOne.git
# aptitude install python-stdeb python-concurrent.futures
$ cd GateOne
$ python setup.py --command-packages=stdeb.command bdist_deb
$ cd deb_dist
# dpkg -i ./gateone_1.2.0-1_all.deb

Le paquet produit n'est pas conforme à la sauce debian. Notamment, il utilise le répertoire /opt/ pour placer l'ensemble du programme ainsi qu'une partie de la configuration. Dans la pratique, ça ne change pas grand chose. La configuration est gérée dans /opt/gateone/settings dans un format un peu bizarre. En effet, les directives de configuration sont au format JSON, ce que je trouve loin d'être lisible. Les fichiers .conf de ce répertoire sont lus dans l'ordre alphabétique.

Néanmoins, si vous tentez d'utiliser GateOne sur Debian Wheezy (mon cas), vous aurez quelques difficultés. En effet, certains paquets ne sont pas à la bonne version. C'est notamment le cas de python-tornado. Vous pouvez utiliser la version de Debian Jessie et l'installer manuellement avec dpkg. Il m'a fallu également ajouter le paquet python-concurrent.futures pour pouvoir lancer gateone.

Si vous voulez juste tester le logiciel, il suffit de le lancer une première fois. GateOne s'occupe alors de créer des fichiers de configuration initiaux dans /opt/gateone/settings. Notamment, le fichier 10server.conf qui gère le lancement du service gateone. Vient ensuite le fichier 20authentication.conf qui gère la partie authentification qui est reglée par défaut sur Pam. Enfin, on trouve un fichier 50terminal.conf chargé de créer une "application" de connexion de terminal via SSH. De ce que j'en retiens, on pourrait imaginer de créer une autre application genre le lancement de mutt. Tous les réglages sont expliqués dans la documentation officielle.

Évaluation

Maintenant que GateOne est lancé, il faut l'évaluer. Il est d'abord beaucoup plus complexe à configurer. Les nombreux fichiers pour le régler finement en attestent. Les fonctionnalités de GateOne sont plus nombreuses également. Ainsi, il propose la gestion de plusieurs terminaux, de conserver les logs de connexions ou encore de revisualiser une session. Il est donc beaucoup plus orienté professionnel où l'on doit se servir en permanence de plusieurs terminaux sur plusieurs machines différentes. Le terminal de GateOne propose lui aussi la détection des URL pour les ouvrir dans le navigateur.

Une fonction qui peut sembler gadget est la possibilité de rejouer une session en cliquant sur la timeline située en bas de l'écran. On peut alors revoir tout ce qui s'est passé dans le terminal depuis le début de la session. C'est important pour un serveur de bastion où on doit pouvoir tracer l'activité des administrateurs.

GateOne propose également un système de marques-pages qui permet de se connecter sur plusieurs serveurs différents en un clic. Enfin, on peut noter la présence d'un plugin SSH qui permet de gérer vos clefs ainsi que de répliquer des sessions SSH.

J'ai également effectué le test du ls -R / et de ce côté, c'est moins flatteur. En effet, le process python qui fait tourner GateOne se met à consommer une puissance CPU qui n'a rien à voir avec celle de shellinabox (50% d'un CPU au lieu de 2%) et il n'y avait qu'un seul utilisateur du côté serveur. En conséquence, je pense que GateOne n'est pas adapté pour tourner sur un Sheevaplug ou tout autre serveur à la puissance limitée. Je n'irai donc pas plus loin dans les tests même si cet outil me semble fonctionnellement un cran au dessus de Shellinabox.

Conclusion

De ces petits tests de logiciels de terminaux web, je retiendrai que Shellinabox correspond tout à fait à mes besoins. Il est simple à gérer, peu gourmand, bien intégré à Debian et sans fioritures. On peut facilement l'intégrer à une configuration Apache existante. GateOne est intéressant dans ses fonctionnalités. On sent qu'il veut se faire un peu plus professionnel, notamment avec la timeline et les options de gestion de SSH. Je le vois plus comme une solution de serveur de bastion où tout passerait par le navigateur Web.

Posted dim. 24 nov. 2013 16:05:35 Tags: