You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Andrew Green <an...@article7.co.uk> on 2018/12/06 15:25:18 UTC

Re: Upgrading a mod_perl application from Apache 2.2 to Apache 2.4

Hi all,

Huge thanks to everyone for your replies on this.  I’ve now been able to work through everything, and I thought I’d post a quick update with some additional notes in case there’s anyone else in the same boat searching the archives in the future!


1. I was able to use the following as a way of determining which version of Apache is in use at runtime:

my $server_version = Apache2::ServerUtil::get_server_banner();
my $is_old_apache = ($server_version =~ /Apache\/2\.2/) ? 1 : 0;


2. My app sets up authen and authz handlers dynamically, from a trans handler. André was right, this was by far the biggest pain point!

My before code looked like this:

$r->push_handlers(PerlMapToStorageHandler => sub {
   $r->add_config(['Require valid-user']);
   $r->add_config(['AuthType cookie']);
});

$r->set_handlers(PerlAuthenHandler => [MyApp::Authen]);
$r->set_handlers(PerlAuthzHandler => [MyApp::Authz]);

As far as I can tell, I have to pre-declare the new Authz provider in my server config:

PerlAddAuthzProvider myapp MyApp::Authz

I didn’t find a way of doing that bit dynamically at runtime.

But I can still conditionally trigger the provider for individual requests from my trans handler, like this:

$r->push_handlers(PerlMapToStorageHandler => sub {
   $r->add_config(['Require myapp']);
});

$r->set_handlers(PerlAuthenHandler => [MyApp::Authen]);


3. Combining #1 and #2 meant I’m able to have the same trans handler run under both Apache 2.2 and 2.4.  I was also able to get my authz handler to run under both by:

a. Having the call to Apache2::Compat -compile happen in the server startup.pl, and not in my module.

b. Wrapping the return value like this:

sub authz_granted {

   my $self = shift;

   # So this compiles under old Apache
   no strict 'subs';

   if ($self->is_old_apache) {
      return Apache2::Const::OK;
   } else {
      return Apache2::Const::AUTHZ_GRANTED;
   }

}


Thanks again to you all for your help.

Cheers,
Andrew.

-- 
Andrew Green
Article Seven Limited
http://www.article7.co.uk/ <http://www.article7.co.uk/>

Article Seven Limited is a registered company in England and Wales.  Registered number: 5703656. Registered office: 10 Hamilton Road, Sidcup, Kent, DA15 7HB.





Re: Upgrading a mod_perl application from Apache 2.2 to Apache 2.4

Posted by Michael Schout <ms...@gkg.net>.
On 12/6/18 9:25 AM, Andrew Green wrote:

> As far as I can tell, I have to pre-declare the new Authz provider in my
> server config:
> 
> PerlAddAuthzProvider myapp MyApp::Authz

Yes this is correct, authz providers must be declared globally under 2.4

I realize this thread is old by now, but for the record, there is a bit
of documentation about how things changed/work under 2.4 in my
Apache2::AuthCookie dist [1].  The way authentication and authorization
works under 2.4 is quite different.

> b. Wrapping the return value like this:
> 
> sub authz_granted {
> 
>    my $self = shift;
> 
>    # So this compiles under old Apache
>    no strict 'subs';
> 
>    if ($self->is_old_apache) {
>       return Apache2::Const::OK;
>    } else {
>       return Apache2::Const::AUTHZ_GRANTED;
>    }
> 
> }

Note that under 2.4, your authz handler gets called twice per request.
The first time, no user will be set, and this is so you can handle
authorization of anonymous requests.  You should return
AUTHZ_DENIED_NO_USER for these requests (unless of course you want to
authorize anonymous requests, in which case you can return AUTHZ_GRANTED
etc).  So something like:

  unless (defined $r->user) {
    return Apache2::Const::AUTHZ_DENIED_NO_USER;
  }

If $r->user *is* set, then you are expected to return one of:

AUTHZ_DENIED
AUTHZ_GRANTED
AUTHZ_GENERAL_ERROR
AUTHZ_NEUTRAL

Also of note, if all you are doing is "Require valid-user", or "Require
user foo" for example, Apache provides an authz provider that already
handles that (see mod_authz_user.c).  So you only need to do this if you
are writing custom authz requirements.

1:
https://metacpan.org/pod/release/MSCHOUT/Apache-AuthCookie-3.27/README.apache-2.4.pod

Regards,
Michael Schout

Re: Upgrading a mod_perl application from Apache 2.2 to Apache 2.4

Posted by "André Warnier (tomcat)" <aw...@ice-sa.com>.
On 07.12.2018 09:29, Andrew Green wrote:
> Hi William,
>
>> Ahhh, ok, just be aware the get_server_description call doesn't exist in 2.2, you need
>> to perform a little eval() magic to guard against that expected failure.
>
> That doesn’t seem right — it returns the following when I try it on a 2.2 box:
>
> /Apache/2.2.22 (Ubuntu) mod_apreq2-20090110/2.8.0/
>
> Perhaps it’s inconsistent across distributions?
>

Just for info : because of the kind of issues mentioned above, I used another solution :

On the 2.4+ boxes :

   PerlSetVar AP_VERSION "20410"

then later :
  	my $ap_version = $r->dir_config('AP_VERSION');

Not subtle, but works for me.

What I did have more trouble with, are the new constants defined only in 2.4+, and which 
are necessary for the authentication.
Apache2::Const::AUTHZ_DENIED_NO_USER etc..
and I have not found a clean way to "define" these under Apache 2.2, so that at least my 
auth modules code *compiles* correctly (under both 2.2 and 2.4).

Other issues I encountered are more in the domain of combining my own auth/authz modules, 
with other auth/authz add-ons like Shibboleth, LDAP etc..
The logic of Apache 2.4 (and of these modules) makes it much more confusing as to what is 
called when and how many times..
I think I've mostly worked it out now, but it does not make for particularly clean code, 
or clean Apache config files, or an easy way to document this for other people less-well 
acquainted with the inner beauties of mod_perl.

I may also have a go in the future at trying the kind of "dynamic" config which Andrew 
showed earlier in this thread.
(With probably the same for-others documentation issues)

It would also be a good idea to at least document this a little bit in the on-line 
mod_perl docs, but I don't know who is in charge of that nowadays, or how to possibly 
contribute to it.



Re: Upgrading a mod_perl application from Apache 2.2 to Apache 2.4

Posted by Andrew Green <an...@article7.co.uk>.
Hi William,

> Ahhh, ok, just be aware the get_server_description call doesn't exist in 2.2, you need
> to perform a little eval() magic to guard against that expected failure. 

That doesn’t seem right — it returns the following when I try it on a 2.2 box:

Apache/2.2.22 (Ubuntu) mod_apreq2-20090110/2.8.0

Perhaps it’s inconsistent across distributions?

Cheers,
Andrew.

-- 
Andrew Green
Article Seven Limited
http://www.article7.co.uk/ <http://www.article7.co.uk/>

Article Seven Limited is a registered company in England and Wales.  Registered number: 5703656. Registered office: 10 Hamilton Road, Sidcup, Kent, DA15 7HB.





Re: Upgrading a mod_perl application from Apache 2.2 to Apache 2.4

Posted by William A Rowe Jr <wr...@rowe-clan.net>.
On Thu, Dec 6, 2018 at 3:34 PM Andrew Green <an...@article7.co.uk> wrote:

> Hi William,
>
> But you are better off looking at;
>
> http://perl.apache.org/docs/2.0/api/Apache2/ServerUtil.html#C_get_server_version_
>
> which returns nothing except exactly what you are asking.
>
>
> I did try this (and it worked fine) — but I kept seeing the following
> error pop up in the logs:
>
> *ap_get_server_version() is deprecated since httpd/2.3.0 try using
> ap_get_server_(description|banner)() instead*
>
> So I switched to banner.  I’ll see about switching again to description.
>

Ahhh, ok, just be aware the get_server_description call doesn't exist in
2.2, you need
to perform a little eval() magic to guard against that expected failure.

Re: Upgrading a mod_perl application from Apache 2.2 to Apache 2.4

Posted by Andrew Green <an...@article7.co.uk>.
Hi William,

> But you are better off looking at;
> http://perl.apache.org/docs/2.0/api/Apache2/ServerUtil.html#C_get_server_version_ <http://perl.apache.org/docs/2.0/api/Apache2/ServerUtil.html#C_get_server_version_>
> 
> which returns nothing except exactly what you are asking.

I did try this (and it worked fine) — but I kept seeing the following error pop up in the logs:

ap_get_server_version() is deprecated since httpd/2.3.0 try using ap_get_server_(description|banner)() instead

So I switched to banner.  I’ll see about switching again to description.

Cheers,
Andrew.

-- 
Andrew Green
Article Seven Limited
http://www.article7.co.uk/ <http://www.article7.co.uk/>

Article Seven Limited is a registered company in England and Wales.  Registered number: 5703656. Registered office: 10 Hamilton Road, Sidcup, Kent, DA15 7HB.





Re: Upgrading a mod_perl application from Apache 2.2 to Apache 2.4

Posted by William A Rowe Jr <wr...@rowe-clan.net>.
On Thu, Dec 6, 2018 at 9:25 AM Andrew Green <an...@article7.co.uk> wrote:

> Hi all,
>
> Huge thanks to everyone for your replies on this.  I’ve now been able to
> work through everything, and I thought I’d post a quick update with some
> additional notes in case there’s anyone else in the same boat searching the
> archives in the future!
>
> 1. I was able to use the following as a way of determining which version
> of Apache is in use at runtime:
>
> my $server_version = Apache2::ServerUtil::get_server_banner();
> my $is_old_apache = ($server_version =~ /Apache\/2\.2/) ? 1 : 0;
>

Just a little warning, the server_banner is controlled by the admin, and
may not include
the entire Apache/2.2 token. The server_description fleshed this out beyond
the control
of the admin, but isn't meant for transmission;

/**
 * Get the server banner in a form suitable for sending over the
 * network, with the level of information controlled by the
 * ServerTokens directive.
 * @return The server banner
 */
AP_DECLARE(const char *) ap_get_server_banner(void);

/**
 * Get the server description in a form suitable for local displays,
 * status reports, or logging.  This includes the detailed server
 * version and information about some modules.  It is not affected
 * by the ServerTokens directive.
 * @return The server description
 */
AP_DECLARE(const char *) ap_get_server_description(void);

But you are better off looking at;
http://perl.apache.org/docs/2.0/api/Apache2/ServerUtil.html#C_get_server_version_

which returns nothing except exactly what you are asking.