SOAP server (#970)
This commit is contained in:
parent
b24343bd10
commit
1983842f79
|
@ -1,3 +1,4 @@
|
||||||
|
* updateStatus( Main, SOAP server )
|
||||||
* replace SOAP calls in Handler/Lib/AuthBasic and Auth/Proxy
|
* replace SOAP calls in Handler/Lib/AuthBasic and Auth/Proxy
|
||||||
* replace SOAP by REST for notification creation
|
* replace SOAP by REST for notification creation
|
||||||
* "mail" in UserDB/*
|
* "mail" in UserDB/*
|
||||||
|
|
|
@ -126,7 +126,7 @@ sub _connect {
|
||||||
if ( $self->{proxyOptions} ) {
|
if ( $self->{proxyOptions} ) {
|
||||||
push @args, %{ $self->{proxyOptions} };
|
push @args, %{ $self->{proxyOptions} };
|
||||||
}
|
}
|
||||||
$self->{ns} ||= 'urn:Lemonldap/NG/Common/CGI/SOAPService';
|
$self->{ns} ||= 'urn:Lemonldap/NG/Common/PSGI/SOAPService';
|
||||||
return $self->{service} = SOAP::Lite->ns( $self->{ns} )->proxy(@args);
|
return $self->{service} = SOAP::Lite->ns( $self->{ns} )->proxy(@args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use bytes;
|
||||||
use strict;
|
use strict;
|
||||||
use SOAP::Transport::HTTP;
|
use SOAP::Transport::HTTP;
|
||||||
|
|
||||||
our @ISA = ('SOAP::Transport::HTTP');
|
our @ISA = ('SOAP::Transport::HTTP::Server');
|
||||||
|
|
||||||
our $VERSION = '2.0.0';
|
our $VERSION = '2.0.0';
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@ sub new {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return $self if ref $self;
|
return $self if ref $self;
|
||||||
|
|
||||||
$self = $self->SUPER::new(@_);
|
my $class = ref($self) || $self;
|
||||||
|
$self = $class->SUPER::new(@_);
|
||||||
SOAP::Trace::objects('()');
|
SOAP::Trace::objects('()');
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
|
|
|
@ -15,9 +15,9 @@ our $VERSION = '2.0.0';
|
||||||
# @param @func authorizated methods
|
# @param @func authorizated methods
|
||||||
# @return Lemonldap::NG::Common::PSGI::SOAPService object
|
# @return Lemonldap::NG::Common::PSGI::SOAPService object
|
||||||
sub new {
|
sub new {
|
||||||
my ( $class, $obj, @func ) = @_;
|
my ( $class, $obj, $req, @func ) = @_;
|
||||||
s/.*::// foreach (@func);
|
s/.*::// foreach (@func);
|
||||||
return bless { obj => $obj, func => \@func }, $class;
|
return bless { obj => $obj, func => \@func, req => $req }, $class;
|
||||||
}
|
}
|
||||||
|
|
||||||
## @method datas AUTOLOAD()
|
## @method datas AUTOLOAD()
|
||||||
|
@ -30,7 +30,7 @@ sub AUTOLOAD {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
$AUTOLOAD =~ s/.*:://;
|
$AUTOLOAD =~ s/.*:://;
|
||||||
if ( grep { $_ eq $AUTOLOAD } @{ $self->{func} } ) {
|
if ( grep { $_ eq $AUTOLOAD } @{ $self->{func} } ) {
|
||||||
my $tmp = $self->{obj}->$AUTOLOAD(@_);
|
my $tmp = $self->{obj}->$AUTOLOAD( $self->{req}, @_ );
|
||||||
unless ( ref($tmp) and ref($tmp) eq 'SOAP::Data' ) {
|
unless ( ref($tmp) and ref($tmp) eq 'SOAP::Data' ) {
|
||||||
$tmp = SOAP::Data->name( result => $tmp );
|
$tmp = SOAP::Data->name( result => $tmp );
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ sub createSession {
|
||||||
|
|
||||||
my $soapClient = SOAP::Lite->proxy( $class->tsv->{portal}->(),
|
my $soapClient = SOAP::Lite->proxy( $class->tsv->{portal}->(),
|
||||||
default_headers => $soapHeaders )
|
default_headers => $soapHeaders )
|
||||||
->uri('urn:Lemonldap::NG::Common::CGI::SOAPService');
|
->uri('urn:Lemonldap/NG/Common/PSGI/SOAPService');
|
||||||
|
|
||||||
my $creds = $class->header_in('Authorization');
|
my $creds = $class->header_in('Authorization');
|
||||||
$creds =~ s/^Basic\s+//;
|
$creds =~ s/^Basic\s+//;
|
||||||
|
|
|
@ -956,7 +956,11 @@ sub attributes {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
documentation => 'Enable SOAP services',
|
documentation => 'Enable SOAP services',
|
||||||
},
|
},
|
||||||
exportedAttr => { type => 'text', },
|
exportedAttr => {
|
||||||
|
type => 'text',
|
||||||
|
documentation =>
|
||||||
|
'List of attributes to export by SOAP or REST servers',
|
||||||
|
},
|
||||||
|
|
||||||
## Virtualhosts
|
## Virtualhosts
|
||||||
|
|
||||||
|
|
|
@ -372,6 +372,7 @@ t/32-Auth-and-issuer-OIDC-authorization_code.t
|
||||||
t/32-Auth-and-issuer-OIDC-hybrid.t
|
t/32-Auth-and-issuer-OIDC-hybrid.t
|
||||||
t/32-Auth-and-issuer-OIDC-implicit.t
|
t/32-Auth-and-issuer-OIDC-implicit.t
|
||||||
t/33-Auth-and-issuer-OpenID2.t
|
t/33-Auth-and-issuer-OpenID2.t
|
||||||
|
t/34-Auth-Proxy-and-SOAP-Server.t
|
||||||
t/40-Notifications-DBI.t
|
t/40-Notifications-DBI.t
|
||||||
t/50-IssuerGet.t
|
t/50-IssuerGet.t
|
||||||
t/90-translations.t
|
t/90-translations.t
|
||||||
|
|
|
@ -13,12 +13,12 @@ our $VERSION = '2.0.0';
|
||||||
sub init {
|
sub init {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
$self->conf->{soapSessionService} ||=
|
$self->conf->{soapSessionService} ||=
|
||||||
$self->conf->{soapAuthService} . 'index.pl/sessions';
|
$self->conf->{soapAuthService} . '/sessions';
|
||||||
$self->conf->{soapSessionService} =~ s/\.plindex.pl/\.pl/;
|
$self->conf->{soapSessionService} =~ s/\.plindex.pl/\.pl/;
|
||||||
$self->conf->{remoteCookieName} ||= $self->conf->{cookieName};
|
$self->conf->{remoteCookieName} ||= $self->conf->{cookieName};
|
||||||
|
|
||||||
unless ( defined $self->conf->{soapAuthService} ) {
|
unless ( defined $self->conf->{soapSessionService} ) {
|
||||||
$self->error("Missing soapAuthService parameter");
|
$self->error("Missing soapSessionService parameter");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -32,7 +32,7 @@ sub getUser {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
return PE_OK if ( $req->datas->{_proxyQueryDone} );
|
return PE_OK if ( $req->datas->{_proxyQueryDone} );
|
||||||
my $soap = SOAP::Lite->proxy( $self->conf->{soapSessionService} )
|
my $soap = SOAP::Lite->proxy( $self->conf->{soapSessionService} )
|
||||||
->uri('urn:Lemonldap::NG::Common::CGI::SOAPService');
|
->uri('urn:Lemonldap/NG/Common/PSGI/SOAPService');
|
||||||
my $r = $soap->getCookies( $req->{user}, $req->datas->{password} );
|
my $r = $soap->getCookies( $req->{user}, $req->datas->{password} );
|
||||||
if ( $r->fault ) {
|
if ( $r->fault ) {
|
||||||
$self->lmLog(
|
$self->lmLog(
|
||||||
|
@ -65,7 +65,7 @@ sub setSessionInfo {
|
||||||
return PE_OK if ( $req->datas->{_setSessionInfoDone} );
|
return PE_OK if ( $req->datas->{_setSessionInfoDone} );
|
||||||
my $soap =
|
my $soap =
|
||||||
SOAP::Lite->proxy( $self->conf->{soapSessionService} )
|
SOAP::Lite->proxy( $self->conf->{soapSessionService} )
|
||||||
->uri('urn:Lemonldap::NG::Common::CGI::SOAPService');
|
->uri('urn:Lemonldap/NG/Common/PSGI/SOAPService');
|
||||||
my $r = $soap->getAttributes( $req->datas->{_remoteId} );
|
my $r = $soap->getAttributes( $req->datas->{_remoteId} );
|
||||||
if ( $r->fault ) {
|
if ( $r->fault ) {
|
||||||
$self->lmLog(
|
$self->lmLog(
|
||||||
|
|
|
@ -36,8 +36,10 @@ sub enabledPlugins {
|
||||||
#}
|
#}
|
||||||
|
|
||||||
# Check if SOAP is enabled
|
# Check if SOAP is enabled
|
||||||
# TODO: REST
|
push @res, '::Plugins::SOAPServer' if ( $self->conf->{Soap} );
|
||||||
push @res, 'SOAP' if ( $self->conf->{Soap} );
|
|
||||||
|
# Check if REST is enabled
|
||||||
|
push @res, '::Plugins::RESTServer' if ( $self->conf->{rest} );
|
||||||
|
|
||||||
# Check if notification is enabled
|
# Check if notification is enabled
|
||||||
push @res, '::Plugins::Notifications' if ( $self->conf->{notifications} );
|
push @res, '::Plugins::Notifications' if ( $self->conf->{notifications} );
|
||||||
|
|
|
@ -129,6 +129,7 @@ sub do {
|
||||||
return $req->response;
|
return $req->response;
|
||||||
}
|
}
|
||||||
if ( !$self->conf->{noAjaxHook} and $req->wantJSON ) {
|
if ( !$self->conf->{noAjaxHook} and $req->wantJSON ) {
|
||||||
|
$self->lmLog('Processing to JSON response','debug');
|
||||||
if ( $err > 0 and !%{ $req->sessionInfo } ) {
|
if ( $err > 0 and !%{ $req->sessionInfo } ) {
|
||||||
return [
|
return [
|
||||||
401,
|
401,
|
||||||
|
@ -170,9 +171,11 @@ sub do {
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
my ( $tpl, $prms ) = $self->display($req);
|
my ( $tpl, $prms ) = $self->display($req);
|
||||||
|
$self->lmLog("Calling sendHtml with template $tpl",'debug');
|
||||||
return $self->sendHtml( $req, $tpl, params => $prms );
|
return $self->sendHtml( $req, $tpl, params => $prms );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
$self->lmLog('Calling autoredirect','debug');
|
||||||
return $self->autoRedirect($req);
|
return $self->autoRedirect($req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,6 +230,7 @@ sub autoRedirect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
my ( $tpl, $prms ) = $self->display($req);
|
my ( $tpl, $prms ) = $self->display($req);
|
||||||
|
$self->lmLog("Calling sendHtml with template $tpl",'debug');
|
||||||
return $self->sendHtml( $req, $tpl, params => $prms );
|
return $self->sendHtml( $req, $tpl, params => $prms );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,8 +148,7 @@ sub getCookies {
|
||||||
|
|
||||||
# Launch process
|
# Launch process
|
||||||
else {
|
else {
|
||||||
$req->{error} = $self->p->process(
|
$req->steps(
|
||||||
$req,
|
|
||||||
[
|
[
|
||||||
qw(getUser setAuthSessionInfo),
|
qw(getUser setAuthSessionInfo),
|
||||||
@{ $self->p->betweenAuthAndDatas },
|
@{ $self->p->betweenAuthAndDatas },
|
||||||
|
@ -157,6 +156,7 @@ sub getCookies {
|
||||||
@{ $self->p->afterDatas },
|
@{ $self->p->afterDatas },
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
$req->{error} = $self->p->process($req);
|
||||||
$self->lmLog(
|
$self->lmLog(
|
||||||
"SOAP authentication result for $user: code $req->{error}",
|
"SOAP authentication result for $user: code $req->{error}",
|
||||||
'debug' );
|
'debug' );
|
||||||
|
@ -176,7 +176,9 @@ sub getCookies {
|
||||||
}
|
}
|
||||||
push @tmp, SOAP::Data->name( cookies => \SOAP::Data->value(@cookies) );
|
push @tmp, SOAP::Data->name( cookies => \SOAP::Data->value(@cookies) );
|
||||||
my $res = SOAP::Data->name( session => \SOAP::Data->value(@tmp) );
|
my $res = SOAP::Data->name( session => \SOAP::Data->value(@tmp) );
|
||||||
$self->p->updateStatus($req);
|
|
||||||
|
#TODO: updateStatus
|
||||||
|
#$self->p->updateStatus($req);
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +211,7 @@ sub getAttributes {
|
||||||
push @tmp, SOAP::Data->name( error => 0 )->type('int');
|
push @tmp, SOAP::Data->name( error => 0 )->type('int');
|
||||||
push @tmp,
|
push @tmp,
|
||||||
SOAP::Data->name( attributes =>
|
SOAP::Data->name( attributes =>
|
||||||
_buildSoapHash( $session->data, @{ $self->exportedAttr($req) } )
|
_buildSoapHash( $session->data, @{ $self->exportedAttr } )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
my $res = SOAP::Data->name( session => \SOAP::Data->value(@tmp) );
|
my $res = SOAP::Data->name( session => \SOAP::Data->value(@tmp) );
|
||||||
|
|
|
@ -50,7 +50,7 @@ sub proxyQuery {
|
||||||
return PE_OK if ( $self->{_proxyQueryDone} );
|
return PE_OK if ( $self->{_proxyQueryDone} );
|
||||||
my $soap =
|
my $soap =
|
||||||
SOAP::Lite->proxy( $self->{soapAuthService} )
|
SOAP::Lite->proxy( $self->{soapAuthService} )
|
||||||
->uri('urn:Lemonldap::NG::Common::CGI::SOAPService');
|
->uri('urn:Lemonldap/NG/Common/CGI/SOAPService');
|
||||||
my $r = $soap->getCookies( $self->{user}, $self->{password} );
|
my $r = $soap->getCookies( $self->{user}, $self->{password} );
|
||||||
if ( $r->fault ) {
|
if ( $r->fault ) {
|
||||||
$self->abort( "Unable to query authentication service",
|
$self->abort( "Unable to query authentication service",
|
||||||
|
@ -79,7 +79,7 @@ sub setSessionInfo {
|
||||||
return PE_OK if ( $self->{_setSessionInfoDone} );
|
return PE_OK if ( $self->{_setSessionInfoDone} );
|
||||||
my $soap =
|
my $soap =
|
||||||
SOAP::Lite->proxy( $self->{soapSessionService} )
|
SOAP::Lite->proxy( $self->{soapSessionService} )
|
||||||
->uri('urn:Lemonldap::NG::Common::CGI::SOAPService');
|
->uri('urn:Lemonldap/NG/Common/CGI/SOAPService');
|
||||||
my $r = $soap->getAttributes( $self->{_remoteId} );
|
my $r = $soap->getAttributes( $self->{_remoteId} );
|
||||||
if ( $r->fault ) {
|
if ( $r->fault ) {
|
||||||
$self->abort( "Unable to query authentication service",
|
$self->abort( "Unable to query authentication service",
|
||||||
|
|
127
lemonldap-ng-portal/t/34-Auth-Proxy-and-SOAP-Server.t
Normal file
127
lemonldap-ng-portal/t/34-Auth-Proxy-and-SOAP-Server.t
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
use Test::More;
|
||||||
|
use strict;
|
||||||
|
use IO::String;
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
require 't/test-lib.pm';
|
||||||
|
}
|
||||||
|
|
||||||
|
my $maintests = 4;
|
||||||
|
my $debug = 'error';
|
||||||
|
my ( $issuer, $sp, $res );
|
||||||
|
my %handlerOR = ( issuer => [], sp => [] );
|
||||||
|
|
||||||
|
SKIP: {
|
||||||
|
eval 'use SOAP::Lite';
|
||||||
|
if ($@) {
|
||||||
|
skip 'SOAP::Lite not found', $maintests;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok( $issuer = issuer(), 'Issuer portal' );
|
||||||
|
$handlerOR{issuer} = \@Lemonldap::NG::Handler::Main::Reload::_onReload;
|
||||||
|
switch ('sp');
|
||||||
|
|
||||||
|
ok( $sp = sp(), 'SP portal' );
|
||||||
|
$handlerOR{sp} = \@Lemonldap::NG::Handler::Main::Reload::_onReload;
|
||||||
|
|
||||||
|
# Simple SP access
|
||||||
|
my $res;
|
||||||
|
ok(
|
||||||
|
$res = $sp->_get(
|
||||||
|
'/', accept => 'text/html',
|
||||||
|
),
|
||||||
|
'Unauth SP request'
|
||||||
|
);
|
||||||
|
expectOK($res);
|
||||||
|
|
||||||
|
# Try to auth
|
||||||
|
ok(
|
||||||
|
$res = $sp->_post(
|
||||||
|
'/', IO::String->new('user=dwho&password=dwho'),
|
||||||
|
length => 23,
|
||||||
|
accept => 'text/html'
|
||||||
|
),
|
||||||
|
'Post user/password'
|
||||||
|
);
|
||||||
|
expectRedirection( $res, 'http://auth.sp.com' );
|
||||||
|
expectCookie($res);
|
||||||
|
}
|
||||||
|
|
||||||
|
count($maintests);
|
||||||
|
clean_sessions();
|
||||||
|
done_testing( count() );
|
||||||
|
|
||||||
|
# Redefine LWP methods for tests
|
||||||
|
no warnings 'redefine';
|
||||||
|
|
||||||
|
sub LWP::UserAgent::request {
|
||||||
|
my ( $self, $req ) = @_;
|
||||||
|
ok( $req->uri =~ m#http://auth.((?:id|s)p).com(.*)#, 'SOAP request' );
|
||||||
|
my $host = $1;
|
||||||
|
my $url = $2;
|
||||||
|
my $res;
|
||||||
|
my $s = $req->content;
|
||||||
|
my $client = ( $host eq 'idp' ? $issuer : $sp );
|
||||||
|
ok(
|
||||||
|
$res = $client->_post(
|
||||||
|
$url,
|
||||||
|
IO::String->new($s),
|
||||||
|
length => length($s),
|
||||||
|
type => $req->header('Content-Type'),
|
||||||
|
custom => {
|
||||||
|
HTTP_SOAPACTION => $req->header('Soapaction'),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
'Execute request'
|
||||||
|
);
|
||||||
|
expectOK($res);
|
||||||
|
ok( getHeader( $res, 'Content-Type' ) =~ m#^(?:text|application)/xml#,
|
||||||
|
'Content is XML' )
|
||||||
|
or explain( $res->[1], 'Content-Type => application/xml' );
|
||||||
|
my $httpResp = HTTP::Response->new( $res->[0], 'OK' );
|
||||||
|
|
||||||
|
while ( my $name = shift @{ $res->[1] } ) {
|
||||||
|
$httpResp->header( $name, shift( @{ $res->[1] } ) );
|
||||||
|
}
|
||||||
|
$httpResp->content( join( '', @{ $res->[2] } ) );
|
||||||
|
count(3);
|
||||||
|
return $httpResp;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub switch {
|
||||||
|
my $type = shift;
|
||||||
|
@Lemonldap::NG::Handler::Main::Reload::_onReload = @{
|
||||||
|
$handlerOR{$type};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub issuer {
|
||||||
|
return LLNG::Manager::Test->new(
|
||||||
|
{
|
||||||
|
ini => {
|
||||||
|
logLevel => $debug,
|
||||||
|
templatesDir => 'site/htdocs/static',
|
||||||
|
domain => 'idp.com',
|
||||||
|
portal => 'http://auth.idp.com',
|
||||||
|
authentication => 'Demo',
|
||||||
|
userDB => 'Demo',
|
||||||
|
Soap => 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub sp {
|
||||||
|
return LLNG::Manager::Test->new(
|
||||||
|
{
|
||||||
|
ini => {
|
||||||
|
logLevel => $debug,
|
||||||
|
domain => 'sp.com',
|
||||||
|
portal => 'http://auth.sp.com',
|
||||||
|
authentication => 'Proxy',
|
||||||
|
userDB => 'Proxy',
|
||||||
|
soapSessionService => 'http://auth.idp.com/sessions',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
|
@ -332,7 +332,7 @@ sub _post {
|
||||||
'SERVER_PORT' => '80',
|
'SERVER_PORT' => '80',
|
||||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||||
( $args{custom} ? %{ $args{custom} } : () ),
|
( $args{custom} ? %{ $args{custom} } : () ),
|
||||||
'psgix.input.buffered' => 1,
|
'psgix.input.buffered' => 0,
|
||||||
'psgi.input' => $body,
|
'psgi.input' => $body,
|
||||||
'CONTENT_LENGTH' => $args{length} // scalar( ( stat $body )[7] ),
|
'CONTENT_LENGTH' => $args{length} // scalar( ( stat $body )[7] ),
|
||||||
'CONTENT_TYPE' => $args{type}
|
'CONTENT_TYPE' => $args{type}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user