Handler.pm 12.6 KB
Newer Older
1 2 3 4 5
## @file
# Alias for Lemonldap::NG::Handler::SharedConf

## @class
# Alias for Lemonldap::NG::Handler::SharedConf
6 7
package Lemonldap::NG::Handler;

8
our $VERSION = '1.3.0';
9 10
use Lemonldap::NG::Handler::SharedConf;
use base qw(Lemonldap::NG::Handler::SharedConf);
11 12 13 14 15 16 17

1;

__END__

=pod

Xavier Guimard's avatar
Xavier Guimard committed
18 19
=encoding utf8

20 21
=head1 NAME

22 23
Lemonldap::NG::Handler - The Apache protection module part of
Lemonldap::NG Web-SSO system.
24 25 26 27 28 29 30 31

=head1 SYNOPSIS

=head2 Create your Apache module

Create your own package (example using a central configuration database):

  package My::Package;
Xavier Guimard's avatar
Xavier Guimard committed
32 33
  use Lemonldap::NG::Handler::SharedConf;
  @ISA = qw(Lemonldap::NG::Handler::SharedConf);
34 35 36 37 38 39
  
  __PACKAGE__->init ( {
    # Local storage used for sessions and configuration
    localStorage        => "Cache::DBFile",
    localStorageOptions => {...},
    # How to get my configuration
Xavier Guimard's avatar
Xavier Guimard committed
40 41 42 43
    configStorage       => {
        type                => "DBI",
        dbiChain            => "DBI:mysql:database=lemondb;host=$hostname",
        dbiUser             => "lemonldap",
44
        dbiPassword         => "password",
Xavier Guimard's avatar
Xavier Guimard committed
45
    }
46 47
    # Uncomment this to activate status module
    # status                => 1,
48 49 50 51 52 53 54 55 56
  } );

=head2 Configure Apache

Call your package in /apache-dir/conf/httpd.conf:

  # Load your package
  PerlRequire /My/File
  # TOTAL PROTECTION
57
  PerlHeaderParserHandler My::Package
58 59
  # OR SELECTED AREA
  <Location /protected-area>
60
    PerlHeaderParserHandler My::Package
61 62 63 64 65 66 67 68 69 70
  </Location>

The configuration is loaded only at Apache start. Create an URI to force
configuration reload, so you don't need to restart Apache at each change:

  # /apache-dir/conf/httpd.conf
  <Location /location/that/I/ve/choosed>
    Order deny,allow
    Deny from all
    Allow from my.manager.com
71
    PerlHeaderParserHandler My::Package->refresh
72
  </Location>
Xavier Guimard's avatar
Xavier Guimard committed
73
  
74 75 76 77 78 79
You can also disable access control for specific URIs, but be aware that
this is not really secure, since session cookies are sent to the protected
application (so they could be spoofed), and since a user could forge his
own HTTP request headers and they would not be reset. To disable access
control for specific URIs on a secure way, you should set access rule to
'skip' instead.
Xavier Guimard's avatar
Xavier Guimard committed
80 81 82 83 84

  <Files "*.gif">
    PerlHeaderParserHandler My::Package->unprotect
  </Files>

85 86 87 88 89 90 91 92 93
To display the status page, add something like this :

  <Location /status>
    Order deny,allow
    Allow from 10.1.1.0/24
    Deny from all
    PerlHeaderParserHandler My::Package->status
  </Location>

94
If your application has a "logout" URL, you can configure it directly in Apache
95 96
configuration file (or in the manager interface). THIS IS DEPRECATED, use the
manager :
97 98 99 100

  <Location /logout>
    PerlHeaderParserHandler My::Package->logout
  </Location>
101 102 103 104 105 106 107 108 109 110

=head1 DESCRIPTION

Lemonldap::NG is a modular Web-SSO based on Apache::Session modules. It
simplifies the build of a protected area with a few changes in the application.

It manages both authentication and authorization and provides headers for
accounting. So you can have a full AAA protection for your web space as
described below.

111
The Apache module part works both with Apache 1.3.x and 2.x ie mod_perl 1 and 2
Xavier Guimard's avatar
Xavier Guimard committed
112
but B<not with mod_perl 1.99>.
113

114
=head2 Authentication, Authorization, Accounting
115 116 117

=head3 B<Authentication>

Xavier Guimard's avatar
Xavier Guimard committed
118
If a user isn't authenticated and attempts to connect to an area protected by a
119 120 121 122 123
Lemonldap::NG compatible handler, he is redirected to a portal. The portal
authenticates user with a ldap bind by default, but you can also use another
authentication sheme like using x509 user certificates (see
L<Lemonldap::NG::Portal::AuthSSL> for more).

124 125
Lemonldap::NG use session cookies generated by L<Apache::Session> so as secure
as a 128-bit random cookie. You may use the C<securedCookie> options of
126 127
L<Lemonldap::NG::Portal> to avoid session hijacking.

128 129 130 131
You have to manage life of sessions by yourself since Lemonldap::NG knows
nothing about the L<Apache::Session> module you've choosed, but it's very easy
using a simple cron script because L<Lemonldap::NG::Portal> stores the start
time in the C<_utime> field.
132 133 134 135 136 137 138 139 140 141 142 143 144 145
By default, a session stay 10 minutes in the local storage, so in the worth
case, a user is authorized 10 minutes after he lost his rights.

=head3 B<Authorization>

Authorization is controled only by handlers because the portal knows nothing
about the way the user will choose. When configuring your Web-SSO, you have to:

=over

=item * choose the ldap attributes you want to use to manage accounting and
authorization (see C<exportedHeaders> parameter in L<Lemonldap::NG::Portal>
documentation).

146
=item * create Perl expressions to define user groups (using ldap attributes)
147 148 149 150 151 152

=item * create an array foreach virtual host associating URI regular
expressions and Perl expressions to use to grant access.

=back

Xavier Guimard's avatar
Xavier Guimard committed
153 154
=head4 Example (See L<Lemonldap::NG::Manager> to see how configuration is
stored)
155

156 157
Exported variables (values will be stored in session database by
L<Lemonldap::NG::Portal>):
158 159 160 161 162 163 164

  exportedVars => {
      cn            => "cn",
      departmentUID => "departmentUID",
      login         => "uid",
  },

165 166
User groups (values will be stored in session database by
L<Lemonldap::NG::Portal>):
167 168 169 170 171 172

  groups => {
      group1 => '{ $departmentUID eq "unit1" or $login = "xavier.guimard" }',
      ...
  },

173
Area protection:
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

  locationRules => {
      www1.domain.com => {
          '^/protected/.*$' => '$groups =~ /\bgroup1\b/',
          default           => 'accept',
      },
      www2.domain.com => {
          '^/site/.*$' => '$uid eq "xavier.guimard" or $groups =~ /\bgroup2\b/',
          '^/(js|css)' => 'accept',
          default      => 'deny',
      },
  },

=head4 Performance

You can use Perl expressions as complicated as you want and you can use all
190 191 192
the exported LDAP attributes (and create your own attributes: with 'macros'
mechanism. See L<Lemonldap::NG::Manager>) in groups evaluations, area
protections or custom HTTP headers (you just have to call them with a "$").
193 194 195 196 197

You have to be careful when choosing your expressions:

=over

198 199
=item * C<groups> and C<macros> are evaluated each time a user is redirected to
the portal,
200

201 202
=item * C<locationRules> and C<exportedheaders> are evaluated for each request
on a protected area.
203 204 205

=back

Xavier Guimard's avatar
Xavier Guimard committed
206
It is also recommended to use the C<groups> mechanism to avoid having to
207 208 209 210 211 212 213 214
evaluate a long expression at each HTTP request:

  locationRules => {
      www1.domain.com => {
          '^/protected/.*$' => '$groups =~ /\bgroup1\b/',
      },
  },

215 216
You can also use LDAP filters, or Perl expression or mixed expressions in
C<groups> parameter. Perl expressions has to be enclosed with C<{}>:
217 218 219 220 221 222 223 224 225 226 227

=over

=item * C<group1 =E<gt> '(|(uid=xavier.guimard)(ou=unit1))'>

=item * C<group1 =E<gt> '{$uid eq "xavier.guimard" or $ou eq "unit1"}'>

=item * C<group1 =E<gt> '(|(uid=xavier.guimard){$ou eq "unit1"})'>

=back

Xavier Guimard's avatar
Xavier Guimard committed
228
It is also recommended to use Perl expressions to avoid requiering the LDAP
229 230 231 232 233 234 235 236 237 238 239 240 241
server more than 2 times per authentication.

=head3 B<Accounting>

=head4 I<Logging portal access>

L<Lemonldap::NG::Portal> doesn't log anything by default, but it's easy to overload
C<log> method for normal portal access or using C<error> method to know what
was wrong if C<process> method has failed.

=head4 I<Logging application access>

Because an handler knows nothing about the protected application, it can't do
242 243 244
more than logging URL. As Apache does this fine, L<Lemonldap::NG::Handler>
gives it the name to used in logs. The C<whatToTrace> parameters indicates
which variable Apache has to use (C<$uid> by default).
245 246 247 248

The real accounting has to be done by the application itself which knows the
result of SQL transaction for example.

249 250 251 252 253
Lemonldap::NG can export HTTP headers either using a proxy or protecting
directly the application. By default, the C<Auth-User> field is used but you
can change it using the C<exportedHeaders> parameters (stored in the
configuration database). This parameters contains an associative array per
virtual host:
254 255 256

=over

Xavier Guimard's avatar
Xavier Guimard committed
257
=item * B<keys> are the names of the chosen headers
258

259
=item * B<values> are Perl expressions where you can use user datas stored in
260 261 262 263 264 265 266 267 268 269 270 271 272
the global store by calling them C<$E<lt>varnameE<gt>>.

=back

Example:

  exportedHeaders => {
      www1.domain.com => {
          'Auth-User' => '$uid',
          'Unit'      => '$ou',
      },
      www2.domain.com => {
          'Authorization' => '"Basic ".encode_base64($employeeNumber.":dummy")',
273
          'Remote-IP'     => '$ip',
274 275 276
      },
  }

277
=head2 Session storage systems
278 279 280 281 282 283 284 285 286 287

Lemonldap::NG use 3 levels of cache for authenticated users:

=over

=item * an Apache::Session::* module choosed with the C<globalStorage>
parameter (completed with C<globalStorageOptions>) and used by
L<lemonldap::NG::Portal> to store authenticated user parameters,

=item * a L<Cache::Cache> module choosed with the C<localStorage> parameter
288
(completed with C<localStorageOptions>) and used to share authenticated users
289 290
between Apache's threads or processus and of course between virtual hosts,

291 292 293
=item * Lemonldap::NG::Handler variables: if the same user use the same thread
or processus a second time, no request are needed to grant or refuse access.
This is very efficient with HTTP/1.1 Keep-Alive system.
294 295 296

=back

297 298
So the number of request to the central storage is limited to 1 per active
user each 10 minutes.
299 300 301 302

Lemonldap::NG is very fast, but you can increase performance using a
L<Cache::Cache> module that does not use disk access.

303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
=head2 Logout system

Lemonldap::NG provides a single logout system: you can use it by adding a link
to the portal with "logout=1" parameter in the portal (See
L<Lemonldap::NG::Portal>) and/or by configuring handler to intercept some URL
(See Sinopsys). The logout system:

=over

=item * delete session in the global session storage,

=item * replace Lemonldap::NG cookie by '',

=item * delete handler caches only if logout action was started from a
protected application and only in the current Apache server. So in other
servers, session is still in cache for 10 minutes maximum if the user was
connected on it in the last 10 minutes.

=back

323 324 325
You can also configure rules in the Manager interface to intercept logout URL.
See L<Lemonldap::NG::Manager> and L<Lemonldap::NG::Handler> for more.

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
=head1 USING LEMONLDAP::NG::HANDLER FOR DEVELOPMENT

Lemonldap::NG::Handler provides different modules:

=over

=item * L<Lemonldap::NG::Handler::Simple>: base module. It can be used
directly to protect a single host.

=item * L<Lemonldap::NG::Handler::Vhost>: module used to managed virtual hosts.

=item * L<Lemonldap::NG::Handler::SharedConf>: with this module, the
configuration can be centralized. Inherits from
L<Lemonldap::NG::Handler::Vhost> and L<Lemonldap::NG::Handler::Simple>.

Xavier Guimard's avatar
Xavier Guimard committed
341 342 343 344
=item * L<Lemonldap::NG::Handler::CGI>: if you have only a few Perl CGI to
protect, you can use this module in your CGI instead of protecting it under
L<Lemonldap::NG::Handler::SharedConf>.

345 346 347 348 349 350 351 352 353 354 355 356 357 358
=item * L<Lemonldap::NG::Handler::Proxy>: this module isn't used to manage
security but is written to create a reverse-proxy without using mod_proxy. In
some case, mod_proxy does not manage correctly some redirections, that is why
this module still exists.

=back

All those modules are compatible both with Apache and mod_perl version 1 and 2,
but NOT with mod_perl 1.99. If you use Linux distributions like Debian Sarge
who provide mod_perl 1.99 for Apache2, you have to use Apache-1.3 or to
download a mod_perl2 backport.

=head1 SEE ALSO

Xavier Guimard's avatar
Xavier Guimard committed
359
L<Lemonldap::NG::Handler::SharedConf>,
360
L<Lemonldap::NG::Portal>, L<Lemonldap::NG::Manager>,
361
L<http://lemonldap-ng.org/>
362 363 364

=head1 AUTHOR

365 366 367 368 369 370 371 372 373
=over

=item Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>

=item François-Xavier Deltombe, E<lt>fxdeltombe@gmail.com.E<gt>

=item Xavier Guimard, E<lt>x.guimard@free.frE<gt>

=back
374

Xavier Guimard's avatar
Xavier Guimard committed
375 376 377
=head1 BUG REPORT

Use OW2 system to report bug or ask for features:
Xavier Guimard's avatar
Xavier Guimard committed
378
L<http://jira.ow2.org>
Xavier Guimard's avatar
Xavier Guimard committed
379 380 381 382 383 384

=head1 DOWNLOAD

Lemonldap::NG is available at
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>

385 386
=head1 COPYRIGHT AND LICENSE

387 388 389 390 391 392 393 394 395
=over

=item Copyright (C) 2006, 2007, 2008, 2009, 2010, 2012 by Xavier Guimard, E<lt>x.guimard@free.frE<gt>

=item Copyright (C) 2012 by François-Xavier Deltombe, E<lt>fxdeltombe@gmail.com.E<gt>

=item Copyright (C) 2006, 2009, 2010, 2011, 2012 by Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>

=back
396 397

This library is free software; you can redistribute it and/or modify
398 399 400 401 402 403 404 405 406 407 408
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<http://www.gnu.org/licenses/>.
409 410

=cut