Avant-propos

Cet article a pour but de mettre en place une journalisation par utilisateur dans le cadre de l’utilisation d’une machine de développement web multi-utilisateur. Chacun des développeurs dispose d’un accès à la machine et d’un espace personnel dans lequel il effectue ses développements. Le serveur apache2 est configuré de en utilisant un seul vhost gérant un sous-domaine par développeur. Dans la suite, nous considérerons que ce domaine est domain.tld.
On ne s’intéresse qu’au cas d’un serveur web ne servant pas de page en HTTPS. Cependant, la configuration et la méthode sont strictement identiques. Le script d’écriture des logs tient d’ailleurs compte de ce cas.

Paramétrage DNS

On suppose que votre serveur DNS est configuré correctement pour faire correspondre domain.tld à l’adresse IP du serveur WEB. Notez ici que si vous serveur dispose de plusieurs adresses, nous ne nous intéressons qu’au cas d’une adresse IP unique ; des adaptations seront donc peut-être à apporter si vous avez plusieurs adresses sur la machine.
On suppose également que le serveur est configuré de sorte que n’importe quel nom de la forme user.domain.tld pointe également sur l’adresse IP du serveur.

Paramètrage des comptes utilisateurs

Les fichiers journaux seront stockés dans le répertoire /home/login/log. Ce paramètre est configurable dans le fichier de configuration du script.
La première étape consiste donc à créer ce répertoire pour chacun de vos utilisateurs :

	# mkdir /home/{login1,login2,...,loginN}/log

Le script d’écriture sera lancé sous l’identité sous laquelle sont lancés les fils apache2 : l’information est récupérée grâce aux paramètres fournis dans /etc/apache2/envvars.

Notez que le script nécessite peut-être des adaptations si vous n’êtes pas dans un environnement «debian standard». Si tel est le cas, adapatez la fonction get_apache_user du script décrit plus loin.

On suppose désormais que votre serveur apache tourne sous l’identité www-data. Adaptez les droits des répertoires que vous venez de créer :

	# chown www-data: /home/{login1,login2,...,loginN}/log
	# chmod 775 /home/{login1,login2,...,loginN}/log

Il est possible que vos utilisateurs n’aient pas les droits de lecture sur les fichiers qui seront créés. Si tel est le cas, je vous conseille d’utiliser les ACL :

	# setfacl -m default:group:devel:rx /home/{login1,login2,...,loginN}/log

devel est le groupe dont font partie vos développeurs.

Installation du script

On suppose que votre machine dispose d’une version fonctionnelle de Perl (le contraire serait étonnant, mais bon ;)) Créez le fichier /usr/local/bin/apache_log.pl avec le contenu suivant :

	#!/usr/bin/perl

	use strict;
	use warnings;
	use Carp;

	my $apache_log_dir  = "/var/log/apache2";
	my $apache_conf_file= "/etc/apache2/envvars";

	my $user_log_prefix = "/home";
	my $user_log_dir    = "log";

	my $uid             = 0;
	my $gid             = 0;

	my $user            = "root";
	my $group           = "root";

	# Read the user name from apache configuration.
	# Must be adapted if you do not run apache2 in a standard
	# debian environment.
	sub get_apache_user() {
	    open(APACHE2, $apache_conf_file);
	    my @conf = ;
	    close(APACHE2);

	    my @userLine  = grep(/APACHE_RUN_USER/, @conf);
	    my @groupLine = grep(/APACHE_RUN_GROUP/, @conf);

	    ( $user       = $userLine[0]  ) =~ s/.*APACHE_RUN_USER=(.*)n$/$1/;
	    ( $group      = $groupLine[0] ) =~ s/.*APACHE_RUN_GROUP=(.*)n$/$1/;

	    return ( $user, $group );
	}

	# Change the UID and the GID of the current process to those of apache
	# children.
	sub change_process_identity() {
	    get_apache_user();
	    get_idents();

	    if ( $uid != 0 ) {
		$> = $uid;
	    }

	    if ( $gid != 0 ) {
		$) = $gid;
	    }

	    return;
	}

	# Get the uid and gid of the given user and group
	sub get_idents() {
	    my @uidInfos = getpwnam($user);
	    my @gidInfos = getgrnam($group);

	    if ( @uidInfos || @gidInfos ) {
		$uid = $uidInfos[2];
		$gid = $gidInfos[2];
	    }
	}

	# change the process identity
	my $process = change_process_identity();

	while ( my $line =  ) {
		my @splitted_line = split(/ /, $line);
		my $srvname       = $splitted_line[0];
		my $port          = $splitted_line[1];

		( my $user        = $srvname ) =~ s/(.*).devel.*/$1/;
		my $proto         = ( $port =~ "443" ) ? "ssl_" : "";
		( my $logline     = $line ) =~ s/^$srvname $port //;

		my $filename      = "/home/" . $user . "/log/" . $proto . "apache.log";
		if ( $srvname eq $user ) {
		        $filename = "/var/log/apache2/devel_". $proto . "access.log";
		}

		open(LOG, '>>', $filename);
		print LOG $logline;
		close(LOG);
	}

	exit 0;

Vous pouvez également télécharger ce script ici. Pensez à lui donner les droits d’exécution et à changer le propriétaire en l’utilisateur qui lance apache (dans notre cas, www-data) :

	# chmod ug+x /usr/local/bin/apache_log.pl
	# chown www-data: /usr/local/bin/apache_log.pl

Paramétrage apache

Arrêtez votre serveur apache :

	# /etc/init.d/apache2 stop

Éditez le fichier de configuration de votre vhost gérant le domaine domain.tld (ou bien créez le ;)) :

	<VirtualHost *:80>
		ServerName      domain.tld
		ServerAlias     *.domain.tld
		ServerAdmin     webmaster

		# Le DocumentRoot par défaut
		DocumentRoot /var/www

		# On spécifie un documentroot différent par utilisateur
		VirtualDocumentRoot /home/%1/www

		<Directory /home/*>
		        Options FollowSymLinks MultiViews
		        AllowOverride All
		        Order allow,deny
		        Allow from all
		</Directory>

		# Possible values include: debug, info, notice, warn, error, crit,
		# alert, emerg.
		ErrorLog /var/log/apache2/domain_error.log
		LogLevel warn

		# Format log on 'combined log' definition (see apache2.conf)
		LogFormat "%V %p %h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" domain
		CustomLog "|/usr/local/bin/apache_log.pl" domain
	</VirtualHost>
Notez que vous pouvez procéder d’une manière similaire pour la directive ErrorLog.

Redémarrez alors votre serveur :

	# /etc/init.d/apache2 start

Surveillez les éventuels messages d’erreur :

	# tail -f /var/log/apache2/error.log /var/log/apache2/domain_error.log

Si aucune erreur n’apparaît, c’est que tout fonctionne 😉 Vous devriez voir apparaître les fichiers de journalisation dans les répertoires des utilisateurs dès leur premier accès à leur espace personnel.

Liens

Leave a Reply