Bug 235572

Summary: www/mod_cloudflare: LoadModule line removed during pkg upgrade
Product: Ports & Packages Reporter: Jeremy Chadwick <jdc>
Component: Individual Port(s)Assignee: Jochen Neumeister <joneum>
Status: New ---    
Severity: Affects Only Me CC: jdc
Priority: --- Flags: bugzilla: maintainer-feedback? (joneum)
Version: Latest   
Hardware: Any   
OS: Any   

Description Jeremy Chadwick 2019-02-07 11:21:04 UTC
Description:

Any time the www/mod_cloudflare port/pkg is upgraded via "pkg upgrade", httpd.conf is modified incorrectly -- the LoadModule module_cloudflare line goes completely missing from the config.

In other words: something about the pkg upgrade (deinstall old/install new) process is modifying httpd.conf and being naughty.

I've seen this at least twice now, but most recently today when upgrading from ap24-mod_cloudflare-0.0.2016.6.0 to ap24-mod_cloudflare-2016.10.0.


Impact:

This has dire consequences for servers behind CloudFlare, as Apache logs and relevant Apache-level access rules suddenly stop working because the module is no longer loaded thus $REMOTE_ADDR and related internal Apache bits show CloudFlare's servers, not the real client IP.

I do not have this problem with other pkg'd Apache modules (ex. mod_php72) (see below).


Reproduction:

1. sudo pkg install ap24-mod_cloudflare-0.0.2016.6.0
2. Make sure the proper LoadModule line for module_cloudflare is enabled (present and uncommented) in httpd.conf.
3. sudo pkg update
4. sudo pkg upgrade  (should show ap24-mod_cloudflare-2016.10.0, pick yes, etc.)
5. Find httpd.conf to be missing the LoadModule line


Debugging:

I dug into this minimally and found the following:

$ pkg info -R ap24-mod_cloudflare-2016.10.0
...
scripts {
    post-install = "/usr/local/sbin/apxs -e -A -n cloudflare /usr/local/libexec/apache24/mod_cloudflare.so";
    post-deinstall = <<EOD
/usr/bin/sed -i '' -E '/LoadModule[[:blank:]]+cloudflare_module/d' /usr/local/etc/apache24/httpd.conf
echo "Don't forget to remove all mod_cloudflare-related directives in your httpd.conf"
EOD;
}

Note:

1. post-install using apxs -A, not -a (see below)
2. post-deinstall deletes the LoadModule line from httpd.conf via a sed inline modify

apxs -a and -A flags:

       -a     This activates the module by automatically adding a
              corresponding LoadModule line to Apache's httpd.conf
              configuration file, or by enabling it if it already exists.

       -A     Same as option -a but the created LoadModule directive is
              prefixed with a hash sign (#), i.e., the module is just prepared
              for later activation but initially disabled.

Compare this to mod_php72, which has:

scripts {
    post-install = "/usr/local/sbin/apxs -e -a -n php7 libphp7.so";
    pre-deinstall = "/usr/local/sbin/apxs -e -A -n php7 libphp7.so";
}

Note:

1. post-install is using apxs -a (not -A) to activate the module
2. pre-deinstall is used, not post-deinstall
3. pre-deinstall is using apxs -A (to deactivate the module/comment out the line in httpd.conf)


Workaround:

As a kludge/hack to to catch and deal with this problem, I've been using the following in a separate file in /usr/local/etc/apache24/Includes:

<IfModule !cloudflare_module>
  LoadModule cloudflare_module libexec/apache24/mod_cloudflare.so
</IfModule>


Solution:

Strongly suggest using the same method that mod_php72 uses.  AP_FAST_BUILD and AP_GENPLIST are probably involved, but I do not understand why this particular port behaves so incorrectly on deinstall/reinstall.
Comment 1 Jeremy Chadwick 2019-02-07 11:23:15 UTC
Apologies: in comment #0, please s/module_cloudflare/cloudflare_module/ (when talking about the Apache configuration).

I did not make this mistake in my configs, only in my bug report.  :-)
Comment 2 Jeremy Chadwick 2019-02-07 12:06:36 UTC
I may have figured this out, but consider me quite surprised by what's happening.  Bottom of my comment contains a reproduction demonstration.

1. On pkg uninstall, the sed inplace modify + delete fails; this is easily overlooked/missed by administrators in the midst scrollback.

Why this error happens on my system: /usr/local/etc/apache24/httpd.conf is a symlink to /conf/ME/apache/httpd.conf (because I got sick and tired of ports/pkgs and Apache or module upgrades over the years tweaking my httpd.conf incorrectly and breaking my setup.)

I guess sed -i only works on literal files and does not follow symlinks.  I'm not going to get into a debate about that as I can see it both ways.  Either way, the line is left in place as shown by the grep.

2. On pkg install, the line is mysteriously removed from the config, which seems contrary to what apxs -A says it does.  The symlink is left intact (that's good).

It seems all of this would just Go Away(tm) if we were using apxs for both deinstall (commenting-out) and install (adding and/or uncommenting).  Except maybe it's not that easy:

I suspect some part of Mk/Uses/apache.mk is responsible for this.  Ah yes, here we are: AP_GENLIST is what's responsible for this situation:

https://svnweb.freebsd.org/ports/head/Mk/Uses/apache.mk?revision=479418&view=markup#l399

www/mod_php72 (stub of lang/php72) doesn't trigger use of AP_GENLIST because it uses its own hard-coded plist that calls apxs directly, alleviating the pain:

https://svnweb.freebsd.org/ports/head/lang/php72/pkg-plist.mod?view=markup

Back to AP_GENLIST: I spent quite some time digging through svn history (extra painful due to the fact that Mk/bsd.apache.mk --> Mk/Uses/apache.mk and svnweb does stupid things due to that).  It looks like this use of sed inplace modify, rather than apxs, was introduced 12 years ago:

https://svnweb.freebsd.org/ports?view=revision&revision=194395

So this really looks to be a wider-spread issue than just www/mod_cloudflare, and goes back a very long time (rmember what I said earlier about things tweaking my httpd.conf and making a mess? :-) ).

This method/model could be some legacy bit from Apache 1.x days, but should probably be revisited by someone who works on Apache bits of the the ports Mk framework.   It may be worthwhile to ask ohauer@ and/or pgollucci@ on this matter.

I will accept WONTFIX/INVALID on this if the port maintainer deems it so.



Reproduction example: 

root@mambo:~ # pkg info | grep cloudflare
ap24-mod_cloudflare-2016.10.0  Cloudflare fork of mod_remoteip
root@mambo:~ # grep cloudflare /usr/local/etc/apache24/httpd.conf
LoadModule cloudflare_module  libexec/apache24/mod_cloudflare.so
root@mambo:~ # pkg remove ap24-mod_cloudflare-2016.10.0
Checking integrity... done (0 conflicting)
Deinstallation has been requested for the following 1 packages (of 0 packages in the universe):

Installed packages to be REMOVED:
        ap24-mod_cloudflare-2016.10.0

Number of packages to be removed: 1

Proceed with deinstalling packages? [y/N]: y
[1/1] Deinstalling ap24-mod_cloudflare-2016.10.0...
[1/1] Deleting files for ap24-mod_cloudflare-2016.10.0: 100%
sed: /usr/local/etc/apache24/httpd.conf: in-place editing only works for regular files
Don't forget to remove all mod_cloudflare-related directives in your httpd.conf
root@mambo:~ # grep cloudflare /usr/local/etc/apache24/httpd.conf
LoadModule cloudflare_module  libexec/apache24/mod_cloudflare.so
root@mambo:~ # pkg install ap24-mod_cloudflare-2016.10.0
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 1 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        ap24-mod_cloudflare: 2016.10.0

Number of packages to be installed: 1

9 KiB to be downloaded.

Proceed with this action? [y/N]: y
[1/1] Fetching ap24-mod_cloudflare-2016.10.0.txz: 100%    9 KiB   9.0kB/s    00:01
Checking integrity... done (0 conflicting)
[1/1] Installing ap24-mod_cloudflare-2016.10.0...
[1/1] Extracting ap24-mod_cloudflare-2016.10.0: 100%
[preparing module `cloudflare' in /usr/local/etc/apache24/httpd.conf]
root@mambo:~ # grep cloudflare /usr/local/etc/apache24/httpd.conf
root@mambo:~ #
root@mambo:~ # ls -l /usr/local/etc/apache24/httpd.conf
lrwxr-xr-x  1 root  wheel  26 Oct 21 19:15 /usr/local/etc/apache24/httpd.conf -> /conf/ME/apache/httpd.conf