Commit babb1c17 authored by Xavier Guimard's avatar Xavier Guimard

* New feature: session access via SOAP

parent 7c40292c
......@@ -2,6 +2,7 @@ Revision history for Perl extension Lemonldap::NG::Handler.
0.75 Sat Feb 24 16:36:56
- Adding cross-domain-authentication support
- local configuration overrides global configuration
0.74 Sun Feb 4 19:27:34 2007
- unprotect system documentation
......
......@@ -15,6 +15,7 @@ our $lastReload = 0;
our $reloadTime;
our $childLock = 0;
our $lmConf;
our $localConfig;
BEGIN {
if ( MP() == 2 ) {
......@@ -42,6 +43,7 @@ sub init($$) {
my ( $class, $args ) = @_;
$reloadTime = $args->{reloadTime} || 600;
$class->localInit($args);
$localConfig = $args;
}
sub localInit {
......@@ -100,6 +102,10 @@ sub globalConfUpdate {
# getConf can return an Apache constant in case of error
return $tmp unless ( ref($tmp) );
# Local arguments have a best precedence
foreach ( keys %$tmp ) {
$tmp->{$_} = $localConfig->{$_} if ( $localConfig->{$_} )
}
$class->setConf($tmp);
OK;
}
......
......@@ -544,7 +544,10 @@ Create your own package:
our @ISA = qw(Lemonldap::NG::Handler::Simple);
__PACKAGE__->init ({locationRules => { 'default' => '$ou =~ /brh/'},
__PACKAGE__->init ({
locationRules => {
default => '$ou =~ /brh/'
},
globalStorage => 'Apache::Session::MySQL',
globalStorageOptions => {
DataSource => 'dbi:mysql:database=dbname;host=127.0.0.1',
......
......@@ -48,6 +48,7 @@ example/lmConfig.mysql
example/index.pl
example/soapserver.pl
lib/Lemonldap/NG/Manager.pm
lib/Lemonldap/NG/Manager/Apache/Session/SOAP.pm
lib/Lemonldap/NG/Manager/_HTML.pm
lib/Lemonldap/NG/Manager/_i18n.pm
lib/Lemonldap/NG/Manager/Base.pm
......
package Lemonldap::NG::Manager::Apache::Session::SOAP;
use strict;
use SOAP::Lite;
our $VERSION = 0.1;
# Variables shared with SOAP::Transport::HTTP::Client
my ( $username, $password );
# PUBLIC INTERFACE
sub TIEHASH {
print STDERR "TIEHASH\n";
my $class = shift;
my $session_id = shift;
my $args = shift;
my ( $proxy, $proxyOptions );
die "proxy argument is required"
unless ( $args and $args->{proxy} );
my $self = {
data => { _session_id => $session_id },
modified => 0,
};
foreach (qw(proxy proxyOptions)) {
$self->{$_} = $args->{$_};
}
($username, $password) = ( $args->{username}, $args->{password} );
bless $self, $class;
if (defined $session_id && $session_id) {
die "unexistant session $session_id"
unless( $self->get( $session_id ) );
}
else {
die "unable to create session"
unless( $self->newsession());
}
return $self;
}
sub FETCH {
print STDERR "FETCH\n";
my $self = shift;
my $key = shift;
return $self->{data}->{$key};
}
sub STORE {
print STDERR "STORE\n";
my $self = shift;
my $key = shift;
my $value = shift;
$self->{data}->{$key} = $value;
$self->{modified} = 1;
return $value;
}
sub DELETE {
print STDERR "DELETE\n";
my $self = shift;
my $key = shift;
$self->{modified} = 1;
delete $self->{data}->{$key};
}
sub CLEAR {
print STDERR "CLEAR\n";
my $self = shift;
$self->{modified} = 1;
$self->{data} = {};
}
sub EXISTS {
print STDERR "EXISTS\n";
my $self = shift;
my $key = shift;
return exists $self->{data}->{$key};
}
sub FIRSTKEY {
print STDERR "FIRESTKEY\n";
my $self = shift;
my $reset = keys %{$self->{data}};
return each %{$self->{data}};
}
sub NEXTKEY {
print STDERR "NEXTKEY\n";
my $self = shift;
return each %{$self->{data}};
}
sub DESTROY {
print STDERR "DESTROY\n";
my $self = shift;
$self->save;
}
# INTERNAL SUBROUTINES
sub _connect {
my $self = shift;
return $self->{service} if ( $self->{service} );
my @args = ( $self->{proxy} );
if ( $self->{proxyOptions} ) {
push @args, %{ $self->{proxyOptions} };
}
$self->{ns} ||= 'urn:/Lemonldap/NG/Manager/SOAPService/Sessions';
return $self->{service} = SOAP::Lite->ns( $self->{ns} )->proxy(@args);
}
sub _soapCall {
my $self = shift;
my $func = shift;
return $self->_connect->$func(@_)->result;
}
sub get {
my $self = shift;
my $id = shift;
return $self->{data} = $self->_soapCall( "get", $id );
}
sub newsession {
my $self = shift;
return $self->{data} = $self->_soapCall( "newsession" );
}
sub save {
my $self = shift;
return unless ($self->{modified});
return $self->_soapCall( "set", $self->{_session_id}, $self->{data} );
}
BEGIN {
sub SOAP::Transport::HTTP::Client::get_basic_credentials {
return $username => $password;
}
}
1;
__END__
=head1 NAME
Lemonldap::NG::Manager::Apache::Session::SOAP - Perl extension written to
access to Lemonldap::NG Web-SSO sessions via SOAP.
=head1 SYNOPSIS
=over
=item * With Lemonldap::NG::Handler
package My::Package;
use Lemonldap::NG::Handler::SharedConf;
our @ISA = qw(Lemonldap::NG::Handler::Simple);
__PACKAGE__->init ({
globalStorage => 'Lemonldap::NG::Manager::Apache::Session::SOAP',
globalStorageOptions => {
proxy => 'http://manager/cgi-bin/soapserver.pl',
proxyOptions => {
timeout => 5,
},
},
configStorage => {
... # See Lemonldap::NG::Handler
=item * With Lemonldap::NG::Portal
use Lemonldap::NG::Portal::SharedConf;
my $portal = new Lemonldap::NG::Portal::SharedConf (
globalStorage => 'Lemonldap::NG::Manager::Apache::Session::SOAP',
globalStorageOptions => {
proxy => 'http://manager/cgi-bin/soapserver.pl',
proxyOptions => {
timeout => 5,
},
},
configStorage => {
... # See Lemonldap::NG::Portal
You can also set parameters corresponding to "Apache::Session module" in the
manager.
=back
=head1 DESCRIPTION
Lemonldap::NG::Manager::Conf provides a simple interface to access to
Lemonldap::NG Web-SSO configuration. It is used by L<Lemonldap::NG::Handler>,
L<Lemonldap::NG::Portal> and L<Lemonldap::NG::Manager>.
Lemonldap::NG::Manager::Apache::Session::SOAP used with
L<Lemonldap::NG::Manager::SOAPServer> provides the ability to acces to
Lemonldap::NG sessions via SOAP: They act as a proxy to access to the real
Apache::Session module (set as Lemonldap::NG::Manager::SOAPServer parameter).
=head2 SECURITY
As Lemonldap::NG::Manager::Conf::SOAP use SOAP::Lite, you have to see
L<SOAP::Transport> to know arguments that can be passed to C<proxyOptions>.
Example :
=over
=item * HTTP Basic authentication
SOAP::transport can use basic authentication by rewriting
C<>SOAP::Transport::HTTP::Client::get_basic_credentials>:
package My::Package;
use base Lemonldap::NG::Handler::SharedConf;
# AUTHENTICATION
BEGIN {
sub SOAP::Transport::HTTP::Client::get_basic_credentials {
return 'username' => 'password';
}
}
__PACKAGE__->init ( {
localStorage => "Cache::FileCache",
localStorageOptions => {
'namespace' => 'MyNamespace',
'default_expires_in' => 600,
},
configStorage => {
type => 'SOAP',
proxy => 'http://manager.example.com/soapserver.pl',
},
https => 1,
} );
=item * SSL Authentication
SOAP::transport provides a simple way to use SSL certificate: you've just to
set environment variables.
package My::Package;
use base Lemonldap::NG::Handler::SharedConf;
# AUTHENTICATION
$ENV{HTTPS_CERT_FILE} = 'client-cert.pem';
$ENV{HTTPS_KEY_FILE} = 'client-key.pem';
__PACKAGE__->init ( {
localStorage => "Cache::FileCache",
localStorageOptions => {
'namespace' => 'MyNamespace',
'default_expires_in' => 600,
},
configStorage => {
type => 'SOAP',
proxy => 'http://manager.example.com/soapserver.pl',
},
https => 1,
} );
=back
=head1 SEE ALSO
L<Lemonldap::NG::Manager::SOAPServer>,
L<Lemonldap::NG::Manager>, L<Lemonldap::NG::Manager::Conf::SOAP>,
L<Lemonldap::NG::Handler>, L<Lemonldap::NG::Portal>
=head1 AUTHOR
Xavier Guimard, E<lt>x.guimard@free.frE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2007 by Xavier Guimard
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.8 or,
at your option, any later version of Perl 5 you may have available.
=cut
......@@ -21,17 +21,14 @@ sub _connect {
if ( $self->{proxyOptions} ) {
push @args, %{ $self->{proxyOptions} };
}
$self->{uri} ||= 'urn:/Lemonldap/NG/Manager/SOAPService';
$self->{service} = SOAP::Lite->uri( $self->{uri} )->proxy(@args);
$self->{ns} ||= 'urn:/Lemonldap/NG/Manager/SOAPService/Config';
return $self->{service} = SOAP::Lite->ns( $self->{ns} )->proxy(@args);
}
sub _soapCall {
my $self = shift;
my $func = shift;
$self->_connect;
my $conf = $self->{service}->$func(@_)->result;
return $conf;
return $self->_connect->$func(@_)->result;
}
sub available {
......
......@@ -20,37 +20,58 @@ sub new {
}
bless $self, $class;
# Arguments verification
foreach (qw(configStorage)) {
unless ( $self->{$_} ) {
die qq/The "$_" parameter is required\n/;
if( $self->{type} eq 'sessions' ) {
unless( $self->{realSessionStorage} ) {
die qq/The "realSessionStorage" parameter is required/;
return ();
}
eval "use " . $self->{realSessionStorage};
die $@ if($@);
}
else {
unless ( $self->{configStorage} ) {
die qq/The "configStorage" parameter is required\n/;
return ();
}
$self->{config} = Lemonldap::NG::Manager::Conf->new( $self->{configStorage} );
die "Configuration not loaded" unless $self->{config};
}
$self->{config} = Lemonldap::NG::Manager::Conf->new( $self->{configStorage} );
die "Configuration not loaded" unless $self->{config};
$Lemonldap::NG::Manager::SOAPService::config = $self->{config};
return $self;
}
sub init {
my $self = shift;
if( $self->{type} eq 'sessions' ) {
$Lemonldap::NG::Manager::SOAPService::Sessions::authorizatedFunc =
$self->{authorizatedFunc} || 'get';
$Lemonldap::NG::Manager::SOAPService::Sessions::config = $self;
}
else {
$Lemonldap::NG::Manager::SOAPService::Config::config = $self->{config};
}
}
# Main process
*process = \&start;
sub start {
# Object is not needed actually
# my $self;
my $self;
if ( ref( $_[0] ) and isa( $_[0], __PACKAGE__ ) ) {
# $self = shift;
$self = shift;
}
else {
# $self = shift->new(@_);
shift->new(@_);
$self = shift->new(@_);
}
SOAP::Transport::HTTP::CGI->dispatch_to('Lemonldap::NG::Manager::SOAPService')->handle;
$self->init();
my $service = ($self->{type} eq 'sessions')
? 'Lemonldap::NG::Manager::SOAPService::Sessions'
: 'Lemonldap::NG::Manager::SOAPService::Config';
SOAP::Transport::HTTP::CGI->dispatch_to($service)->handle;
}
# Description of SOAP service
package Lemonldap::NG::Manager::SOAPService;
package Lemonldap::NG::Manager::SOAPService::Config;
our $config;
......@@ -75,13 +96,64 @@ sub load {
return $config->load(@_);
}
package Lemonldap::NG::Manager::SOAPService::Sessions;
our $config;
our $authorizedFunc = 'get';
sub newsession {
return 0 unless( $authorizedFunc =~ /\bnew\b/ );
my( $class, $args ) = @_;
$args ||= {};
my %h;
eval {
tie %h, $config->{realSessionStorage}, undef, $config->{realSessionStorageOptions};
};
return 0 if ($@);
# my $id = $h{_session_id};
$h{$_} = $args->{$_} foreach ( keys %{ $args } );
$h{_utime} = time();
$args->{$_} = $h{$_} foreach ( keys %h );
untie %h;
return $args;
}
sub get {
print STDERR "get\n";
return 0 unless( $authorizedFunc =~ /\bget\b/ );
my( $class, $id ) = @_;
my %h;
eval {
tie %h, $config->{realSessionStorage}, $id, $config->{realSessionStorageOptions};
};
#print STDERR __PACKAGE__:"$@\n";
return 0 if ($@);
my $args;
$args->{$_} = $h{$_} foreach ( keys %h );
untie %h;
return $args;
}
sub set {
return 0 unless( $authorizedFunc =~ /\bset\b/ );
my( $class, $id, $args ) = @_;
my %h;
eval {
tie %h, $config->{realSessionsStorage}, undef, $config->{realSessionsStorageOptions};
};
return 0 if ($@);
$h{$_} = $args->{$_} foreach ( keys %{ $args } );
untie %h;
return $args;
}
1;
__END__
=head1 NAME
Lemonldap::NG::Manager::SOAPServer - Perl extension written to access to
Lemonldap::NG Web-SSO configuration via SOAP.
Lemonldap::NG Web-SSO configuration or sessions via SOAP.
=head1 SYNOPSIS
......@@ -89,16 +161,27 @@ Lemonldap::NG Web-SSO configuration via SOAP.
use Lemonldap::NG::Manager::SOAPServer;
Lemonldap::NG::Manager::SOAPServer->start(
configStorage => {
type=>"File",
dirName=>"/usr/share/doc/lemonldap-ng/examples/conf/"
}
configStorage => {
type => "File",
dirName => "/usr/share/doc/lemonldap-ng/examples/conf/"
},
# 2 types are available :
# * 'config' for configuration access
# * 'sessions' for sessions access
type => 'config',
);
=head2 Client side
See L<Lemonldap::NG::Manager::Conf::SOAP> for documentation on client side.
See L<Lemonldap::NG::Manager::Conf::SOAP> for documentation on client side
configuration access.
See L<Lemonldap::NG::Manager::Apache::Session> for documentation on client side
sessions access.
=head3 Configuration access
=head3 Area protection
=head4 Area protection
package My::Package;
use Lemonldap::NG::Handler::SharedConf;
......@@ -117,7 +200,7 @@ See L<Lemonldap::NG::Manager::Conf::SOAP> for documentation on client side.
https => 0,
} );
=head3 Authentication portal
=head4 Authentication portal
use Lemonldap::NG::Portal::SharedConf;
......@@ -131,7 +214,7 @@ See L<Lemonldap::NG::Manager::Conf::SOAP> for documentation on client side.
if($portal->process()) {
...
=head3 Manager
=head4 Manager
use Lemonldap::NG::Manager;
......@@ -147,6 +230,12 @@ See L<Lemonldap::NG::Manager::Conf::SOAP> for documentation on client side.
$m->doall();
=head3 Sessions access
Use simply Lemonldap::NG::Manager::Apache::Session in the 'Apache session
module'parameter (instead of Apache::Session::MySQL or
Apache::Session::File).
=head1 DESCRIPTION
Lemonldap::NG::Manager::Conf provides a simple interface to access to
......
Revision history for Perl extension Lemonldap::NG::Portal.
0.62 Sat Feb 24 16:34:45
0.62 Wed Feb 28 23:22:14
- Adding cross-domain-authentication mechanism
- local configuration overrides global configuration
0.61 Sun Feb 11 9:10:12
- Existing sessions are now checked
......
......@@ -24,14 +24,22 @@ our $safe = new Safe;
# See Lemonldap::NG::Manager::Conf(3) for more
sub getConf {
my $self = shift;
$self->SUPER::getConf(@_);
my %args;
if ( ref( $_[0] ) ) {
%args = %{ $_[0] };
}
else {
%args = @_;
}
%$self = ( %$self, %args );
$self->{lmConf} =
Lemonldap::NG::Manager::Conf->new( $self->{configStorage} )
unless $self->{lmConf};
return 0 unless ( ref( $self->{lmConf} ) );
my $tmp = $self->{lmConf}->getConf;
return 0 unless $tmp;
$self->{$_} = $tmp->{$_} foreach ( keys %$tmp );
# Local configuration prepends global
$self->{$_} = $args{$_} || $tmp->{$_} foreach ( keys %$tmp );
1;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment