Send Apache errorlogs from a docker container to syslog host - apache

I have a container with apache2 and modsecurity installed.
My question is: how to send the logs generated by apache and modsecurity (stored in /var/apache2/error.log) to the host?
I have syslog within the host that already collect locally and send the logs to a remote server; I'm able to send the logs from other containers correctly but not from the apache container.
I tried several ways but unfortunately i was not able to achieve this objective:
Piping with: ErrorLog "| :514"
ErrorLog /dev/stderr
TransferLog /dev/stdout
Within dockerfile: RUN ln -sf /proc/self/fd/1 /var/log/apache2/access.log &&
ln -sf /proc/self/fd/1 /var/log/apache2/error.log
This is my current configuration:
/etc/apache2/sites-available/000-default.conf
...
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SecRuleEngine On
...
There is a default modsecurity configuration for now.
Thank you.

Related

View error.log and access.log in Apache in Docker?

My Docker has the following in its vhost.conf
<VirtualHost *:80>
// ...(snipped)
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Viewing these via docker exec in /var/log/apache, doing ls -l shows:
access.log -> /dev/stdout
error.log -> /dev/stderr
What does this mean and is it possible to view their content?
docker logs on the container will show you this log output.
/dev/stdout and /dev/stderr are special "files" that actually point at the current process's standard output and error channels, respectively (they should themselves be symlinks to /proc/self/fd/1 and /proc/self/fd/2). Unless something causes them to get redirected somewhere else, this will become the main output of the container, and that gets captured by Docker's internal log subsystem.
If you wanted to capture these as concrete files on your local system, you could bind mount a local directory over /var/log/apache (with a docker run -v option or Docker Compose ports: option). This would cause an (initially empty) directory to hide the contents of that directory in the container, and when the HTTP daemon wrote out its logs, they'd appear as real files in a directory shared with the host.
You should not need docker exec in normal operation.

Unable to call shell script from apache httpd

I am trying to call shell script from 000-default.conf inside /etc/httpd/sites-available.
The 000-default.conf file content is :
<VirtualHost *:80>
ServerName localhost
DocumentRoot /var/www/html/
CustomLog "| sh /scratch/user/test.sh" custom_user_tracking
</VirtualHost>
My /etc/httpd/conf/httpd.conf has below content added:
ServerName localhost
LogFormat "%t [%h] [%m] [%U] [%B] [%b] [%D] [%q] [%s] [%{Referer}i] [%{User-Agent}i]" custom_user_tracking
IncludeOptional sites-enabled/*.conf
IncludeOptional sites-available/*.conf
I have kept a dummy html file inside /var/www/html/
Content of index.html:
<!DOCTYPE html>
<html>
<body>
<h1>Hello World!</h1>
</body>
</html>
When ever I hit http://localhost:80 the shell script is not called at all. The shell script is executable and it just prints "Hello World".
But when I call apache kafka binary from 000-default.conf file then it works properly.
Modified 000-default.conf file:
<VirtualHost *:80>
ServerName localhost
DocumentRoot /var/www/html/
CustomLog "| [HOME_DIR_KAFKA]/bin/kafka-console-producer.sh --topic access-log --broker- list <Remote_host_ip>:9092" custom_user_tracking
</VirtualHost>
Now when I click on http://localhost:80 then message is send in remote kafka server.
Can any one help here how can I call shell script from apache httpd?
Consider making the test.sh script executable using "shebang" ($!), instead of using sh.
000-default.conf :
CustomLog "| /scratch/user/test.sh" custom_user_tracking
/scratch/user/test.sh
#! /bin/sh
...
Alternatively run 'sh' using full path
CustomLog "| /bin/sh /scratch/user/test.sh" custom_user_tracking
Also, double check the execute permission on /scratch/user/test.sh, and the permission on the folder. https is usually running as non-privileged account.
Here is the content of send_message.sh:
#! /bin/sh
PRIVATE_KEY=$1
HOST=$2
TOPIC_NAME=$3
MESSAGE=$4
echo "OCI VM IP : $HOST"
echo "PRIVATE KEY : $PRIVATE_KEY"
echo "TOPIC-NAME: $TOPIC_NAME"
echo "MESSAGE: $MESSAGE"
## Run Cmd in vm
ssh -o "StrictHostKeyChecking no" -i $PRIVATE_KEY opc#$HOST /bin/bash << EOF
sudo su
echo $MESSAGE | [HOME_DIR]/bin/kafka-console-producer.sh --broker-list [VM_IP]:9092 --topic $TOPIC_NAME
EOF
And content of /etc/httpd/sites-available/000-dafult.conf
<VirtualHost *:80>
ServerName localhost
DocumentRoot /var/www/html/
CustomLog "| /home/opc/send_message.sh /home/opc/dev2oci.key 100.111.69.61 access-log apache-httpd" custom_user_tracking
</VirtualHost>
The message is sent in topi access_log for every 5s interval. Though the http://localhost:80 is not triggered from browser.
If I replace the CustomLog with below entry:
CustomLog "| [HOME_DIR]/bin/kafka-console-producer.sh --topic access-log --broker-list [VM_IP]:9092" custom_user_tracking
Then message is sent on triggering http://localhost:80 from browser.
Can anyone let me know what I am missing here.

Apache: Serving content from two different locations and ports

I have an Apache server running on Ubuntu 14 on a server on which I have sudo.
When users request the server's IP, Apache serves content from /var/www/html.
I'd like to keep this behavior intact, and make it so that users who request IP/cats get some special content that's hosted by a Docker container on port 7777.
What's the best way to achieve this functionality in Apache?
With thanks to #arkascha I did the following to get this going:
Create a file /etc/apache2/sites-available/wow.conf with the following content:
<VirtualHost *:*>
# enable proxies
ProxyPreserveHost On
ProxyPass /cats http://0.0.0.0:7777/
ProxyPassReverse /cats http://0.0.0.0:7777/
ServerAdmin douglas.duhaime#yale.edu
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
This says when requests come in for IP/cats, serve the users the content from port 7777.
I then symlinked this file to the sites-enabled directory:
sudo ln /etc/apache2/sites-available/wow.conf /etc/apache2/sites-enabled/wow.conf
Finally, I needed to delete the default sites enabled file and restart the server:
sudo rm /etc/apache2/sites-enabled/000-default.conf
sudo service apache2 restart
P.S. Apache is amazing.

Docker www-data grant write permissions to var/www

I'm running a php:7.0-apache Docker image, but I have no permissions to write to /var/www/html. How is it possible to grant write rights to this user?
Dockerfile:
FROM php:7.0-apache
# PHP Extensions
RUN docker-php-ext-install pdo_mysql
# Composer
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php composer-setup.php
RUN php -r "unlink('composer-setup.php');"
RUN mv composer.phar /usr/local/bin/composer
ADD vhost-default.conf /etc/apache2/sites-enabled/000-default.conf
# Open Ports
EXPOSE 80
EXPOSE 443
Host Conf
<VirtualHost *:80>
ServerAdmin webmaster#localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory /var/www/html >
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
To resolve this you will need to add an extra line in your Dockerfile like:
RUN chown www-data:www-data /var/www/html/
Sergiu's answer is not working, because your volume is bound after chown.
What you should do is that you should run chown after bound to your volume and before start the Apache.
To do that, I add chown command in the apache2-foreground script.
RUN sed -i 's/^exec /chown www-data:www-data \/var\/www\/html/\n\nexec /' /usr/local/bin/apache2-foreground
So when you start your container, it will change the permission to www-data.
PS: Your container's user should be in root or a user who can execute chown.

enable mod_rewrite logs in apache running on ubuntu

I tried to enable logging. I enabled mod rewrite and restarted the computer, for some reason the rewrite log doesn't write to the destination directory /var/lib/log
I'm wondering if anyone had done it before successfully, please post it here so I can give it a try.
cat /etc/issue
Ubuntu 16.04.1 LTS \n \l
apache2 -v
Server version: Apache/2.4.18 (Ubuntu)
Server built: 2016-07-14T12:32:26
/var/log/apache2$ ls
access.log access.log.3.gz error.log.1 error.log.4.gz
access.log.1 access.log.4.gz error.log.10.gz error.log.5.gz
access.log.10.gz access.log.5.gz error.log.11.gz error.log.6.gz
access.log.11.gz access.log.6.gz error.log.12.gz error.log.7.gz
access.log.12.gz access.log.7.gz error.log.13.gz error.log.8.gz
access.log.13.gz access.log.8.gz error.log.14.gz error.log.9.gz
access.log.14.gz access.log.9.gz error.log.2.gz other_vhosts_access.log
access.log.2.gz error.log error.log.3.gz
<VirtualHost *:80>
ServerName odyss{shadow}.odysseysafaris.com
ServerAdmin
DocumentRoot /var/www/html/{shadow}
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory "/var/www/html/{shadow}">
Options FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
Apache doesn't have its own log for mod_rewrite in 2.4. It logs to the error log. See Apache Module mod_rewrite - Logging for full details.
The last section is of particular relevance:
RewriteLog
Those familiar with earlier versions of mod_rewrite will no doubt be
looking for the RewriteLog and RewriteLogLevel directives. This
functionality has been completely replaced by the new per-module
logging configuration mentioned above.
To get just the
mod_rewrite-specific log messages, pipe the log file through grep:
tail -f error_log|fgrep '[rewrite:'
Also you don't appear to have added any directives to activate the logging. Add something like:
LogLevel rewrite:trace1
Which would just change the mod_rewrite logging and not affect any other. See the above link for more info and see LogLevel:
Specifying a level with a module name will set the level for that module only.