Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Although this project started as a development environment for Totara Learn it c
* A [PHPUnit](https://phpunit.de/) and [Behat](http://behat.org/en/latest/) setup to run tests (including [Selenium](https://www.seleniumhq.org/))
* A [MailDev](https://github.com/maildev/maildev?tab=readme-ov-file#maildev) instance to view sent emails
* [Redis](https://redis.io/) for caching and/or session handling
* [ClamAV](https://www.clamav.net/) for antivirus scanning, wired up automatically on PHP 8.4 and 8.5
* [XHProf](https://github.com/tideways/php-xhprof-extension) for profiling
* [XDebug](https://xdebug.org/) installed, ready for debugging with your favorite IDE
* [Excimer](https://www.mediawiki.org/wiki/Excimer) installed, for discovering performance problems
Expand Down
1 change: 1 addition & 0 deletions bin/tdocker
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ source "$project_path/tools/check_for_update.sh"
files=(
"docker-compose.yml"
"compose/apache.yml"
"compose/clamav.yml"
"compose/mariadb.yml"
"compose/mssql.yml"
"compose/mysql.yml"
Expand Down
23 changes: 23 additions & 0 deletions clamav/clamd.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# docker-dev ClamAV daemon configuration, mounted over the stock image's /etc/clamav/clamd.conf.
#
# Only the socket settings differ from the image default. Everything else - logging, the freshclam
# daemon, the clamav user, and creating /run/clamav - is already handled by the stock entrypoint.
# Do not set LogFile: ClamAV rejects /dev/stdout with "Symbolic link loop", and the image already
# logs to stdout.

# Unix socket, shared with the PHP 8.4/8.5 containers via the clamav-socket volume. The stock
# default is /tmp/clamd.sock, which we cannot share without mounting over the whole of /tmp.
# Those containers run clamdscan with --fdpass, which passes the open file descriptor over this
# socket, so clamd never needs to see the scanned file's path or be able to read it itself.
# Mode 0666 so that www-data in the PHP containers can connect.
LocalSocket /run/clamav/clamd.sock
LocalSocketMode 0666

# Exposed for ad-hoc debugging only. Totara cannot use TCP: antivirus_clamav's
# scanner::is_configured() returns false for the tcpsocket running method, so a TCP-configured
# plugin is silently never invoked.
TCPSocket 3310
TCPAddr 0.0.0.0

# Must stay above upload_max_filesize in php/config/php.ini.
StreamMaxLength 100M
24 changes: 24 additions & 0 deletions compose/clamav.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
services:

clamav:
# The default (Alpine) tags are amd64 only - the -debian variants are multiarch.
image: clamav/clamav:stable-debian13-slim
container_name: totara_clamav
restart: ${RESTART_POLICY:-no}
environment:
TZ: ${TIME_ZONE}
volumes:
# Only the socket settings differ from the image default.
- ./clamav/clamd.conf:/etc/clamav/clamd.conf
# Shared with the PHP 8.4/8.5 containers so clamdscan can reach clamd.
- clamav-socket:/run/clamav
# Persists signature updates between runs.
- clamav-data:/var/lib/clamav
networks:
- totara
# No healthcheck here: the image ships HEALTHCHECK --start-period=6m CMD clamdcheck.sh, which
# reads clamd.conf and so already tests the unix socket the PHP containers use.

volumes:
clamav-socket:
clamav-data:
10 changes: 10 additions & 0 deletions compose/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ services:
- bash-history:/root/.bash_history
- zsh-history:/root/.zsh_history
- ./shell:/root/custom_shell
# Lets clamdscan reach clamd in the clamav container (see compose/clamav.yml).
- clamav-socket:/run/clamav
depends_on:
- php-8.4-debug
networks:
Expand Down Expand Up @@ -382,6 +384,8 @@ services:
- bash-history:/root/.bash_history
- zsh-history:/root/.zsh_history
- ./shell:/root/custom_shell
# Lets clamdscan reach clamd in the clamav container (see compose/clamav.yml).
- clamav-socket:/run/clamav
networks:
- totara

Expand Down Expand Up @@ -412,6 +416,8 @@ services:
- bash-history:/root/.bash_history
- zsh-history:/root/.zsh_history
- ./shell:/root/custom_shell
# Lets clamdscan reach clamd in the clamav container (see compose/clamav.yml).
- clamav-socket:/run/clamav
depends_on:
- php-8.5-debug
networks:
Expand Down Expand Up @@ -448,6 +454,8 @@ services:
- bash-history:/root/.bash_history
- zsh-history:/root/.zsh_history
- ./shell:/root/custom_shell
# Lets clamdscan reach clamd in the clamav container (see compose/clamav.yml).
- clamav-socket:/run/clamav
networks:
- totara

Expand All @@ -458,6 +466,7 @@ services:
# - Add a build entry in compose/build.yml
# - Add a mutagen sync entry in compose/sync.yml
# - Add relevant network aliases in compose/nginx.yml and compose/apache.yml
# - Add the clamav-socket volume mount, if the version is 8.4 or newer
# - Add a CI build entry in .github/workflows/build-php.yml
# - Add a image matrix entry in .github/workflows/scan-images.yml
# - Update the max PHP version in .github/workflows/validate-config.yml
Expand All @@ -468,3 +477,4 @@ volumes:
coverage-report:
bash-history:
zsh-history:
clamav-socket:
10 changes: 10 additions & 0 deletions php/config/clamd.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# docker-dev ClamAV client configuration.
#
# This is installed as /etc/clamav/clamd.conf because that is the path clamdscan reads by
# default, and Totara invokes clamdscan without a --config-file argument. There is no clamd
# running in this container - it runs in the clamav container and exposes the socket below
# through the shared clamav-socket volume.
#
# Totara adds --fdpass whenever the configured binary is named clamdscan, which passes the open
# file descriptor over this socket, so clamd does not need to see the scanned file's path.
LocalSocket /run/clamav/clamd.sock
30 changes: 30 additions & 0 deletions php/includes/config-after.php
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,36 @@
$CFG->smtphosts = 'maildev:1025';


// ClamAV antivirus, only active while the clamav container is running.
// clamdscan is invoked with --fdpass (Totara adds that automatically whenever the binary is named
// clamdscan), which hands the open file descriptor to clamd, so the clamav container does not need
// to see the scanned file itself. Note the tcpsocket running method cannot be used here - the
// plugin's is_configured() returns false for it, so it would silently never scan anything.
// Note the stock clamav image does not forward SIGTERM to clamd, so a stopped container leaves its
// socket file behind. Check that something is actually listening rather than just that the file
// exists - connecting to a stale unix socket fails immediately, so this stays cheap.
$DOCKER_DEV->clamav_socket = '/run/clamav/clamd.sock';
$DOCKER_DEV->clamav_running = false;
if (file_exists($DOCKER_DEV->clamav_socket)) {
$clamav_probe = @stream_socket_client('unix://' . $DOCKER_DEV->clamav_socket, $errno, $errstr, 1);
if ($clamav_probe !== false) {
fclose($clamav_probe);
$DOCKER_DEV->clamav_running = true;
}
unset($clamav_probe, $errno, $errstr);
}
if ($DOCKER_DEV->clamav_running) {
$CFG->antiviruses = 'clamav';
$CFG->forced_plugin_settings['antivirus_clamav'] = [
'runningmethod' => 'commandline',
'pathtoclam' => '/usr/bin/clamdscan',
// Never fail a dev upload just because clamd is still loading its signatures.
'clamfailureonupload' => 'donothing',
'tries' => 1,
];
}


// Paths to binaries
$CFG->py3path = '/usr/bin/python3';
$CFG->pathtogs = '/usr/bin/gs';
Expand Down
2 changes: 2 additions & 0 deletions php/php84/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
ghostscript \
graphviz \
aspell \
clamdscan \
libldap2-dev \
libltdl-dev \
libc-client-dev \
Expand Down Expand Up @@ -147,6 +148,7 @@ RUN ln -fs /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime \

COPY config/php.ini /usr/local/etc/php/
COPY config/fpm.conf /usr/local/etc/php-fpm.d/zz-totara.conf
COPY config/clamd.conf /etc/clamav/clamd.conf

# Source each .sh file found in the /shell/ folder, always source the default_aliases.sh file first
RUN echo 'if [[ -e "/root/custom_shell/default-aliases.sh" ]]; then source "/root/custom_shell/default-aliases.sh"; fi' >> ~/.bashrc && \
Expand Down
2 changes: 2 additions & 0 deletions php/php85/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
ghostscript \
graphviz \
aspell \
clamdscan \
libldap2-dev \
libltdl-dev \
libc-client-dev \
Expand Down Expand Up @@ -152,6 +153,7 @@ RUN ln -fs /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime \

COPY config/php.ini /usr/local/etc/php/
COPY config/fpm.conf /usr/local/etc/php-fpm.d/zz-totara.conf
COPY config/clamd.conf /etc/clamav/clamd.conf

# Source each .sh file found in the /shell/ folder, always source the default_aliases.sh file first
RUN echo 'if [[ -e "/root/custom_shell/default-aliases.sh" ]]; then source "/root/custom_shell/default-aliases.sh"; fi' >> ~/.bashrc && \
Expand Down
Loading