diff --git a/debian/control b/debian/control
index 2c9da1a911ca58844e32ac7e816d723fe40266f4..c2f5c0e686ee801a241251f7193d582fd0bace59 100644
--- a/debian/control
+++ b/debian/control
@@ -138,6 +138,16 @@ Description: Lemonldap::NG FastCGI server
Lemonldap::NG FastCGI server provides a Nginx auth_request server that handles
also LLNG Portal and Manager.
+Package: liblemonldap-ng-ssoaas-apache-client-perl
+Architecture: all
+Section: web
+Depends: ${misc:Depends},
+ ${perl:Depends}
+Description: Lemonldap::NG SSOaaS client for Apache
+ Lemonldap::NG is a complete Web-SSO system that provides a SSO-as-a-Service
+ system, natively usable with Nginx. Lemonldap::NG::SSOaaS::Apache::Client
+ permits one to enroll an Apache server into Lemonldap::NG's SSOaaS service.
+
Package: lemonldap-ng-uwsgi-app
Architecture: all
Section: web
diff --git a/debian/liblemonldap-ng-ssoaas-apache-client-perl.install b/debian/liblemonldap-ng-ssoaas-apache-client-perl.install
new file mode 100644
index 0000000000000000000000000000000000000000..584f5aff2dd318f5f86a22a7886fc9707dd307cf
--- /dev/null
+++ b/debian/liblemonldap-ng-ssoaas-apache-client-perl.install
@@ -0,0 +1,2 @@
+usr/share/perl5/Lemonldap/NG/SSOaaS/Apache
+usr/share/man/man3/Lemonldap::NG::SSOaaS::Apache*
diff --git a/lemonldap-ng-handler/MANIFEST b/lemonldap-ng-handler/MANIFEST
index 7ab477de07021e3f703be203f3b1606c504a0d20..e15677941360b342916529ccf6115d2d1732d9b4 100644
--- a/lemonldap-ng-handler/MANIFEST
+++ b/lemonldap-ng-handler/MANIFEST
@@ -56,6 +56,7 @@ lib/Lemonldap/NG/Handler/Server/OAuth2.pm
lib/Lemonldap/NG/Handler/Server/SecureToken.pm
lib/Lemonldap/NG/Handler/Server/ServiceToken.pm
lib/Lemonldap/NG/Handler/Server/ZimbraPreAuth.pm
+lib/Lemonldap/NG/SSOaaS/Apache/Client.pm
lib/Plack/Middleware/Auth/LemonldapNG.pm
Makefile.PL
MANIFEST This list of files
diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm
index 93e381759b1c12ec30a0fc4cbc1d0b7070992692..e1ba1daac6d6e0849c14b2ef71eb3a76afc7b3c3 100644
--- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm
+++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm
@@ -1,184 +1,7 @@
-# Apache2 FastCGI client to query remote LL::NG FastCGI server
-#
package Lemonldap::NG::Handler::ApacheMP2::FCGIClient;
-use strict;
-use Apache2::Connection;
-use Apache2::RequestUtil;
-use Apache2::RequestRec;
-use Apache2::Const -compile =>
- qw(FORBIDDEN HTTP_UNAUTHORIZED REDIRECT OK DECLINED DONE SERVER_ERROR AUTH_REQUIRED HTTP_SERVICE_UNAVAILABLE);
-use Apache2::Log;
-use APR::Table;
-use IO::Socket::INET;
-use FCGI::Client;
-use URI;
-use URI::Escape qw(uri_unescape);
+use Lemonldap::NG::SSOaaS::Apache::Client;
-use constant FORBIDDEN => Apache2::Const::FORBIDDEN;
-use constant HTTP_UNAUTHORIZED => Apache2::Const::HTTP_UNAUTHORIZED;
-use constant REDIRECT => Apache2::Const::REDIRECT;
-use constant DECLINED => Apache2::Const::DECLINED;
-use constant SERVER_ERROR => Apache2::Const::SERVER_ERROR;
-
-our $VERSION = '2.0.15';
-
-sub handler {
- my ( $class, $r ) = @_;
- $r ||= $class;
- my ( $uri, $args ) = ( $r->uri, $r->args );
- my $uri_full = $uri . ( $args ? "?$args" : '' );
- my $env = {
-
- #%ENV,
- HTTP_HOST => $r->hostname,
- REMOTE_ADDR => (
- $r->connection->can('remote_ip')
- ? $r->connection->remote_ip
- : $r->connection->client_ip
- ),
- QUERY_STRING => $args,
- REQUEST_URI => $uri_full,
- PATH_INFO => '',
- SERVER_PORT => $r->get_server_port,
- REQUEST_METHOD => $r->method,
- };
-
- foreach (qw(VHOSTTYPE RULES_URL HTTPS_REDIRECT PORT_REDIRECT)) {
- if ( my $t = $r->dir_config($_) ) {
- $env->{$_} = $t;
- }
- }
-
- $r->headers_in->do(
- sub {
- my $h = shift;
- my $k = uc($h);
- if ( $k ne 'HOST' ) {
- $k =~ s/-/_/g;
- $env->{"HTTP_$k"} = $r->headers_in->{$h};
- }
- return 1;
- }
- );
- $uri = URI->new( "http://" . $r->hostname . $r->unparsed_uri );
- $env->{PATH_INFO} = uri_unescape( $uri->path );
- my ( $host, $port ) = ( $r->dir_config('LLNG_SERVER') =~ /^(.*):(\d+)$/ );
- unless ( $host and $port ) {
- print STDERR 'Missing or bad LLNG_SERVER';
- return SERVER_ERROR;
- }
- my $sock = IO::Socket::INET->new(
- PeerAddr => $host,
- PeerPort => $port,
- ) or die $!;
- foreach ( keys %$env ) {
- delete $env->{$_} unless ( length $env->{$_} );
- }
- my ( $stdout, $stderr, $status ) =
- FCGI::Client::Connection->new( sock => $sock )->request($env);
- my %hdrs =
- map { s/\r//g; m/(.*?):\s*(.*)/; $_ ? ( $1, $2 ) : () } split /\n+/,
- $stdout;
- unless ( $hdrs{Status} =~ /^(\d+)\s+(.*?)$/ ) {
- print STDERR "Bad status line $hdrs{Status}\n";
- return SERVER_ERROR;
- }
- $status = $1;
-
- if ( ( $status == 302 or $status == 401 ) and $hdrs{Location} ) {
- $r->err_headers_out->set( Location => $hdrs{Location} );
- return REDIRECT;
- }
-
- $r->user( $hdrs{'Lm-Remote-User'} ) if $hdrs{'Lm-Remote-User'};
- $r->subprocess_env( REMOTE_CUSTOM => $hdrs{'Lm-Remote-Custom'} )
- if $hdrs{'Lm-Remote-Custom'};
-
- my $i = 1;
- while ( $hdrs{"Headername$i"} ) {
- $r->headers_in->set( $hdrs{"Headername$i"} => $hdrs{"Headervalue$i"} )
- if $hdrs{"Headervalue$i"};
- $i++;
- }
- $status = DECLINED if ( $status < 300 );
-
- return $status;
-}
+our @ISA = ('Lemonldap::NG::SSOaaS::Apache::Client');
1;
-__END__
-
-=pod
-
-=encoding utf8
-
-=head1 NAME
-
-Lemonldap::NG::Handler::ApacheMP2::FCGIClient - Apache client for Lemonldap::NG
-FastCGI server.
-
-=head1 SYNOPSIS
-
-In apache2.conf:
-
-
- PerlHeaderParserHandler Lemonldap::NG::Handler::ApacheMP2::FCGIClient
- PerlSetVar LLNG_SERVER 127.0.0.1:9090
- PerlSetVar VHOSTTYPE DevOps
- # or PerlSetVar VHOSTTYPE DevOpsST
- PerlSetVar RULES_URL http://app.tld/rules.json
- PerlSetVar HOST HTTP_HOST
- PerlSetVar PORT_REDIRECT SERVER_PORT
- PerlSetVar HTTPS_REDIRECT HTTPS
- ...
-
-
-=head1 DESCRIPTION
-
-Lemonldap::NG::Handler::ApacheMP2::FCGIClient is an alternative to
-L that replace inside handler. It calls a
-remote Lemonldap::NG FastCGI server to get authentication, authorization and
-headers.
-
-=head1 SEE ALSO
-
-L,
-L
-
-=head1 AUTHORS
-
-=over
-
-=item LemonLDAP::NG team L
-
-=back
-
-=head1 BUG REPORT
-
-Use OW2 system to report bug or ask for features:
-L
-
-=head1 DOWNLOAD
-
-Lemonldap::NG is available at
-L
-
-=head1 COPYRIGHT AND LICENSE
-
-See COPYING file for details.
-
-This library 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, 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, see L.
-
-=cut
diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/SSOaaS/Apache/Client.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/SSOaaS/Apache/Client.pm
new file mode 100644
index 0000000000000000000000000000000000000000..4aaa40a21df8b5b5a476b743b51597d8e0fe3ffe
--- /dev/null
+++ b/lemonldap-ng-handler/lib/Lemonldap/NG/SSOaaS/Apache/Client.pm
@@ -0,0 +1,184 @@
+# Apache2 FastCGI client to query remote LL::NG FastCGI server
+#
+package Lemonldap::NG::SSOaaS::Apache::Client;
+
+use strict;
+use Apache2::Connection;
+use Apache2::RequestUtil;
+use Apache2::RequestRec;
+use Apache2::Const -compile =>
+ qw(FORBIDDEN HTTP_UNAUTHORIZED REDIRECT OK DECLINED DONE SERVER_ERROR AUTH_REQUIRED HTTP_SERVICE_UNAVAILABLE);
+use Apache2::Log;
+use APR::Table;
+use IO::Socket::INET;
+use FCGI::Client;
+use URI;
+use URI::Escape qw(uri_unescape);
+
+use constant FORBIDDEN => Apache2::Const::FORBIDDEN;
+use constant HTTP_UNAUTHORIZED => Apache2::Const::HTTP_UNAUTHORIZED;
+use constant REDIRECT => Apache2::Const::REDIRECT;
+use constant DECLINED => Apache2::Const::DECLINED;
+use constant SERVER_ERROR => Apache2::Const::SERVER_ERROR;
+
+our $VERSION = '2.0.15';
+
+sub handler {
+ my ( $class, $r ) = @_;
+ $r ||= $class;
+ my ( $uri, $args ) = ( $r->uri, $r->args );
+ my $uri_full = $uri . ( $args ? "?$args" : '' );
+ my $env = {
+
+ #%ENV,
+ HTTP_HOST => $r->hostname,
+ REMOTE_ADDR => (
+ $r->connection->can('remote_ip')
+ ? $r->connection->remote_ip
+ : $r->connection->client_ip
+ ),
+ QUERY_STRING => $args,
+ REQUEST_URI => $uri_full,
+ PATH_INFO => '',
+ SERVER_PORT => $r->get_server_port,
+ REQUEST_METHOD => $r->method,
+ };
+
+ foreach (qw(VHOSTTYPE RULES_URL HTTPS_REDIRECT PORT_REDIRECT)) {
+ if ( my $t = $r->dir_config($_) ) {
+ $env->{$_} = $t;
+ }
+ }
+
+ $r->headers_in->do(
+ sub {
+ my $h = shift;
+ my $k = uc($h);
+ if ( $k ne 'HOST' ) {
+ $k =~ s/-/_/g;
+ $env->{"HTTP_$k"} = $r->headers_in->{$h};
+ }
+ return 1;
+ }
+ );
+ $uri = URI->new( "http://" . $r->hostname . $r->unparsed_uri );
+ $env->{PATH_INFO} = uri_unescape( $uri->path );
+ my ( $host, $port ) = ( $r->dir_config('LLNG_SERVER') =~ /^(.*):(\d+)$/ );
+ unless ( $host and $port ) {
+ print STDERR 'Missing or bad LLNG_SERVER';
+ return SERVER_ERROR;
+ }
+ my $sock = IO::Socket::INET->new(
+ PeerAddr => $host,
+ PeerPort => $port,
+ ) or die $!;
+ foreach ( keys %$env ) {
+ delete $env->{$_} unless ( length $env->{$_} );
+ }
+ my ( $stdout, $stderr, $status ) =
+ FCGI::Client::Connection->new( sock => $sock )->request($env);
+ my %hdrs =
+ map { s/\r//g; m/(.*?):\s*(.*)/; $_ ? ( $1, $2 ) : () } split /\n+/,
+ $stdout;
+ unless ( $hdrs{Status} =~ /^(\d+)\s+(.*?)$/ ) {
+ print STDERR "Bad status line $hdrs{Status}\n";
+ return SERVER_ERROR;
+ }
+ $status = $1;
+
+ if ( ( $status == 302 or $status == 401 ) and $hdrs{Location} ) {
+ $r->err_headers_out->set( Location => $hdrs{Location} );
+ return REDIRECT;
+ }
+
+ $r->user( $hdrs{'Lm-Remote-User'} ) if $hdrs{'Lm-Remote-User'};
+ $r->subprocess_env( REMOTE_CUSTOM => $hdrs{'Lm-Remote-Custom'} )
+ if $hdrs{'Lm-Remote-Custom'};
+
+ my $i = 1;
+ while ( $hdrs{"Headername$i"} ) {
+ $r->headers_in->set( $hdrs{"Headername$i"} => $hdrs{"Headervalue$i"} )
+ if $hdrs{"Headervalue$i"};
+ $i++;
+ }
+ $status = DECLINED if ( $status < 300 );
+
+ return $status;
+}
+
+1;
+__END__
+
+=pod
+
+=encoding utf8
+
+=head1 NAME
+
+Lemonldap::NG::SSOaaS::Apache::Client - Apache client for Lemonldap::NG
+FastCGI server.
+
+=head1 SYNOPSIS
+
+In apache2.conf:
+
+
+ PerlHeaderParserHandler Lemonldap::NG::SSOaaS::Apache::Client
+ PerlSetVar LLNG_SERVER 127.0.0.1:9090
+ PerlSetVar VHOSTTYPE DevOps
+ # or PerlSetVar VHOSTTYPE DevOpsST
+ PerlSetVar RULES_URL http://app.tld/rules.json
+ PerlSetVar HOST HTTP_HOST
+ PerlSetVar PORT_REDIRECT SERVER_PORT
+ PerlSetVar HTTPS_REDIRECT HTTPS
+ ...
+
+
+=head1 DESCRIPTION
+
+Lemonldap::NG::SSOaaS::Apache::Client is an alternative to
+L that replace inside handler. It calls a
+remote Lemonldap::NG FastCGI server to get authentication, authorization and
+headers.
+
+=head1 SEE ALSO
+
+L,
+L
+
+=head1 AUTHORS
+
+=over
+
+=item LemonLDAP::NG team L
+
+=back
+
+=head1 BUG REPORT
+
+Use OW2 system to report bug or ask for features:
+L
+
+=head1 DOWNLOAD
+
+Lemonldap::NG is available at
+L
+
+=head1 COPYRIGHT AND LICENSE
+
+See COPYING file for details.
+
+This library 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, 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, see L.
+
+=cut
diff --git a/rpm/lemonldap-ng.spec b/rpm/lemonldap-ng.spec
index 8b06237b1ae6abe8b9208dcd5509f3db8e93c390..21431c7320911a29506012064c19b8eea467fe06 100644
--- a/rpm/lemonldap-ng.spec
+++ b/rpm/lemonldap-ng.spec
@@ -387,6 +387,16 @@ BuildRequires: selinux-policy-devel
Custom SELinux policy module
%endif
+#==============================================================================
+# SSOaaS client for Apache
+#==============================================================================
+%package -n perl-Lemonldap-NG-SSOaaS-Apache-Client
+Summary: Lemonldap-NG SSOaaS client for Apache
+
+%description -n perl-Lemonldap-NG-SSOaaS-Apache-Client
+This package permits one to enroll an Apache server
+into Lemonldap::NG's SSOaaS service.
+
#==============================================================================
# Source preparation
#==============================================================================
@@ -746,6 +756,10 @@ fi
%ghost %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}
%endif
+%files -n perl-Lemonldap-NG-SSOaaS-Apache-Client
+%{_mandir}/man3/Lemonldap::NG::SSOaaS::Apache*.3pm.*
+%{perl_vendorlib}/Lemonldap/NG/SSOaaS/Apache/
+
#==============================================================================
# Changelog
#==============================================================================