package App::CamelPKI; use warnings; use strict; =head1 NAME App::CamelPKI - A multi-purpose PKI. =head1 VERSION Version 0.02 =cut our $VERSION = '0.04'; =head1 SYNOPSIS script/camel_pki_server.pl =head1 DESCRIPTION Camel-PKI is an X509v3 Certification Authority (CA) programmed in Perl and Catalyst. It relies on L for the low-level cryptographic operations. =cut use Catalyst::Runtime '5.70'; use Catalyst qw/ConfigLoader Static::Simple/; =head1 CONFIGURATION The configuration file is camel_pki.yml. It must be placed at the application root directory. See the bundled file C for syntax details. =cut # When using ConfigLoader (as we do), this is how to set an # overridable default value: __PACKAGE__->config( name => 'App::CamelPKI' ); use App::CamelPKI::RestrictedClassMethod; use App::CamelPKI::Error; use App::CamelPKI::SysV::Apache; __PACKAGE__->setup; =head2 METHODS =head2 model($modelname) Returns an instance of one of the Catalyst generated object model (as in L), or an object with the same API but lesser privilege, depending on the connected user rigths. If user has no rights on $modelname, trigger an exception. The overloading of this method is key to applying capability discipline, because it forces the Principle of Least Authority (POLA) onto Camel-PKI HTTP/S clients. =cut sub model { my ($self, $shortclass) = @_; my $full_model = $self->SUPER::model($shortclass); # Privileges are unconstrained except under Apache. return $full_model if (! App::CamelPKI::SysV::Apache->is_running_under); my $r = $self->engine->apache; my $client_dn = $r->subprocess_env("SSL_CLIENT_S_DN"); my $admin_dn = '/O=CamelPKI.fr/OU=CamelPKI/OU=role/CN=administrator'; # FIXME: privileges are immutable, and that makes the switch-case # below quite messy. In a future version, capabilities will be # fully movable and persisted next to the users that have them, # and this code will morph into a database. if ($shortclass eq "CA") { if (! defined $client_dn) { return $full_model->facet_crl_only; } elsif ($client_dn eq $admin_dn) { return $full_model->facet_operational; } else { warn "User $client_dn unknown"; throw App::CamelPKI::Error::Privilege ("User unknown", -dn => $client_dn); } } else { throw App::CamelPKI::Error::Privilege ("Only CA privileges are available to the controller for now."); } } =head2 setup_components Overloaded from the parent class in order to lock down restricted class methods in the Camel-PKI model after the respective classes are loaded (see L). This only occurs in production (that is, when running under Apache, as determined by L), so that tests can still call restricted methods freely. =cut sub setup_components { my $self = shift; $self->SUPER::setup_components(@_); return unless App::CamelPKI::SysV::Apache->is_running_under; my %brands = App::CamelPKI::RestrictedClassMethod->grab_all; # FIXME: this is just clumsy. We should use one directory # capability for the CA instead (even though # ::RestrictedClassMethod is still useful to some extent eg to # disable debug methods). $brands{"App::CamelPKI::Model::CA"}->invoke ("set_brands", $brands{"App::CamelPKI::CA"}, $brands{"App::CamelPKI::CADB"}); } =head1 SEE ALSO L, L =head1 AUTHOR Dominique QUATRAVAUX, C<< >> Jeremie KLEIN, C<> =head1 COPYRIGHT & LICENCE Copyright 2007 Siemens Business Services S.A.S., all rights reserved. This program is free software; you can redistribute it following the same terms as Perl itself. =cut 1;