251 lines
6.8 KiB
Plaintext
251 lines
6.8 KiB
Plaintext
|
#!/usr/bin/perl
|
||
|
#=============================================================================
|
||
|
# LemonLDAP::NG session conversion tool
|
||
|
#
|
||
|
# This script lets an administrator migrate existing sessions from one backend
|
||
|
# to another. It is mostly useful when run on persistant sessions, but it can be
|
||
|
# useful in some other cases too, such as OIDC Offline sessions
|
||
|
#
|
||
|
# This is part of LemonLDAP::NG product, released under GPL
|
||
|
#=============================================================================
|
||
|
|
||
|
use Lemonldap::NG::Common::Apache::Session;
|
||
|
use Lemonldap::NG::Common::Session;
|
||
|
use Config::IniFiles;
|
||
|
use strict;
|
||
|
use Getopt::Std;
|
||
|
$Getopt::Std::STANDARD_HELP_VERSION = 1;
|
||
|
|
||
|
our $VERSION = "2.0.6";
|
||
|
|
||
|
# Options
|
||
|
# -d: debug mode
|
||
|
# -c: configuration file
|
||
|
# -i: ignore errors
|
||
|
my $opts = {};
|
||
|
getopts( 'dic:', $opts );
|
||
|
|
||
|
my $debug = $opts->{d};
|
||
|
my $config_file = $opts->{c};
|
||
|
my $ignore_errors = $opts->{i};
|
||
|
my $nb_converted = 0;
|
||
|
my $nb_error = 0;
|
||
|
|
||
|
sub HELP_MESSAGE {
|
||
|
my $OUT = shift;
|
||
|
print $OUT <<END_MESSAGE;
|
||
|
|
||
|
$0 [-di] -c config_file.ini
|
||
|
|
||
|
-d Debug mode
|
||
|
-i Ignore errors
|
||
|
|
||
|
This script converts sessions in between the two backends specified in the configuration file
|
||
|
The configuration file must contain the following (adjust to your environment):
|
||
|
|
||
|
[sessions_from]
|
||
|
storageModule = Apache::Session::File
|
||
|
storageModuleOptions = { \\
|
||
|
'Directory' => '/var/lib/lemonldap-ng/sessions', \\
|
||
|
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock', \\
|
||
|
}
|
||
|
# Only convert some session types
|
||
|
# sessionKind = Persistent, SSO
|
||
|
|
||
|
[sessions_to]
|
||
|
storageModule = Apache::Session::Browseable::Postgres
|
||
|
storageModuleOptions = { \\
|
||
|
'DataSource' => 'DBI:Pg:database=lemonldapdb;host=pg.example.com', \\
|
||
|
'UserName' => 'lemonldaplogin', \\
|
||
|
'Password' => 'lemonldappw', \\
|
||
|
'Commit' => 1, \\
|
||
|
'Index' => 'ipAddr _whatToTrace user', \\
|
||
|
'TableName' => 'sessions', \\
|
||
|
}
|
||
|
|
||
|
END_MESSAGE
|
||
|
}
|
||
|
|
||
|
unless ($config_file) {
|
||
|
HELP_MESSAGE( \*STDERR );
|
||
|
die "You must provide the -c option";
|
||
|
}
|
||
|
|
||
|
my $inicfg =
|
||
|
Config::IniFiles->new( -file => $config_file, -allowcontinue => 1 );
|
||
|
my $cfg = {};
|
||
|
|
||
|
die "Could not read configuration file" unless $inicfg;
|
||
|
|
||
|
for my $section (qw/sessions_from sessions_to/) {
|
||
|
die "Could not find section $section in configuration file $config_file"
|
||
|
unless $inicfg->SectionExists($section);
|
||
|
|
||
|
# Load section parameters
|
||
|
my $r;
|
||
|
foreach ( $inicfg->Parameters($section) ) {
|
||
|
$r->{$_} = $inicfg->val( $section, $_ );
|
||
|
|
||
|
# Remove spaces before and after value (#1488)
|
||
|
$r->{$_} =~ s/^\s*(.+?)\s*/$1/;
|
||
|
if ( $r->{$_} =~ /^[{\[].*[}\]]$/ || $r->{$_} =~ /^sub\s*{.*}$/ ) {
|
||
|
eval "\$r->{$_} = $r->{$_}";
|
||
|
if ($@) {
|
||
|
print $@;
|
||
|
return $r;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$cfg->{$section} = $r;
|
||
|
}
|
||
|
|
||
|
my $backendFrom;
|
||
|
my $backendTo;
|
||
|
my @sessionKindOnly;
|
||
|
if ( $cfg->{sessions_from}->{sessionKind} ) {
|
||
|
@sessionKindOnly = split /\W+/, $cfg->{sessions_from}->{sessionKind};
|
||
|
}
|
||
|
|
||
|
if ( $cfg->{sessions_from}->{storageModule} ) {
|
||
|
$backendFrom = $cfg->{sessions_from}->{storageModuleOptions};
|
||
|
$backendFrom->{backend} = $cfg->{sessions_from}->{storageModule};
|
||
|
}
|
||
|
else {
|
||
|
die
|
||
|
"[sessions_from] configuration section does not declare a storageModule";
|
||
|
}
|
||
|
|
||
|
if ( $cfg->{sessions_to}->{storageModule} ) {
|
||
|
$backendTo = $cfg->{sessions_to}->{storageModuleOptions};
|
||
|
$backendTo->{backend} = $cfg->{sessions_to}->{storageModule};
|
||
|
}
|
||
|
else {
|
||
|
die "[sessions_to] configuration section does not declare a storageModule";
|
||
|
}
|
||
|
|
||
|
Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
|
||
|
$backendFrom,
|
||
|
sub {
|
||
|
my $entry = shift;
|
||
|
my $id = shift;
|
||
|
|
||
|
print "Processing session $id\n" if $debug;
|
||
|
my $s = Lemonldap::NG::Common::Session->new( {
|
||
|
storageModule => $backendTo->{backend},
|
||
|
storageModuleOptions => $backendTo,
|
||
|
id => $id,
|
||
|
info => $entry,
|
||
|
force => 1,
|
||
|
}
|
||
|
);
|
||
|
|
||
|
# If filtering sessionKind
|
||
|
if (@sessionKindOnly) {
|
||
|
|
||
|
unless ( grep { $_ eq $entry->{_session_kind} } @sessionKindOnly ) {
|
||
|
return undef;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( $s->error ) {
|
||
|
die "Error encountered on session $id" unless $ignore_errors;
|
||
|
$nb_error += 1;
|
||
|
print "Error converting session $id : " . $s->error . "\n";
|
||
|
}
|
||
|
else {
|
||
|
print "Session $id successfully converted\n" if $debug;
|
||
|
$nb_converted += 1;
|
||
|
}
|
||
|
}
|
||
|
);
|
||
|
|
||
|
print "$nb_converted sessions have been converted\n";
|
||
|
|
||
|
print "$nb_error errors encountered during conversion\n" if $nb_error;
|
||
|
|
||
|
my $exit = $nb_error ? 1 : 0;
|
||
|
exit $exit;
|
||
|
|
||
|
__END__
|
||
|
|
||
|
=head1 NAME
|
||
|
|
||
|
=encoding utf8
|
||
|
|
||
|
convertSessions - A tool to convert Lemonldap::NG sessions between storage backends.
|
||
|
|
||
|
=head1 SYNOPSIS
|
||
|
|
||
|
convertSession [-di] -c parameters.ini
|
||
|
|
||
|
|
||
|
=head1 DESCRIPTION
|
||
|
|
||
|
convertConfig is a command line tool to migrate all sessions stored
|
||
|
in a source backend (sessions_from), into a new backend (sessions_to).
|
||
|
|
||
|
It requires a special configuration file in which you must list the source
|
||
|
and destination backend modules and parameters.
|
||
|
|
||
|
Sessions will not be deleted from the source backend. Existing sessions in the
|
||
|
destination backend will be kept, unless they have the same session ID as a
|
||
|
session in the source backend. In that case, the source will overwrite the
|
||
|
destination.
|
||
|
|
||
|
|
||
|
=head1 CONFIGURATION FILE FORMAT
|
||
|
|
||
|
The configuration file needs two sections to describe the source and destination backends
|
||
|
|
||
|
Here is an example
|
||
|
|
||
|
[sessions_from]
|
||
|
storageModule = Apache::Session::File
|
||
|
storageModuleOptions = { \
|
||
|
'Directory' => '/var/lib/lemonldap-ng/sessions', \
|
||
|
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock', \
|
||
|
}
|
||
|
# Only migrate some session types
|
||
|
# sessionKind = Persistent, SSO
|
||
|
|
||
|
[sessions_to]
|
||
|
storageModule = Apache::Session::Browseable::Postgres
|
||
|
storageModuleOptions = { \
|
||
|
'DataSource' => 'DBI:Pg:database=lemonldapdb;host=pg.example.com', \
|
||
|
'UserName' => 'lemonldaplogin', \
|
||
|
'Password' => 'lemonldappw', \
|
||
|
'Commit' => 1, \
|
||
|
'Index' => 'ipAddr _whatToTrace user', \
|
||
|
'TableName' => 'sessions', \
|
||
|
}
|
||
|
|
||
|
|
||
|
The C<sessionKind> parameter may be used to filter only some session types.
|
||
|
|
||
|
Thanks to this, you can use this script to migrate from one database holding
|
||
|
all your sessions to separate tables from each session type.
|
||
|
|
||
|
|
||
|
=head1 SEE ALSO
|
||
|
|
||
|
L<http://lemonldap-ng.org/>
|
||
|
|
||
|
=head1 AUTHORS
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item Maxime Besson, E<lt>maxime.besson@worteks.comE<gt>
|
||
|
|
||
|
=back
|
||
|
|
||
|
=head1 BUG REPORT
|
||
|
|
||
|
Use OW2 system to report bug or ask for features:
|
||
|
L<https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues>
|
||
|
|
||
|
=head1 DOWNLOAD
|
||
|
|
||
|
Lemonldap::NG is available at
|
||
|
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>
|
||
|
|