Skip to content

Commit

Permalink
Merge pull request #54 from rsundriyal/CLAM-2562-1.4-release
Browse files Browse the repository at this point in the history
Adding 1.4 release
  • Loading branch information
val-ms authored Aug 21, 2024
2 parents 3b5c1b2 + a987fd3 commit 4b79cb9
Show file tree
Hide file tree
Showing 12 changed files with 1,321 additions and 0 deletions.
126 changes: 126 additions & 0 deletions clamav/1.4/alpine/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright (C) 2020 Olliver Schinagl <[email protected]>
# Copyright (C) 2021-2023 Cisco Systems, Inc. and/or its affiliates. All rights reserved.

# hadolint ignore=DL3007 latest is the latest stable for alpine
FROM index.docker.io/library/alpine:latest AS builder

WORKDIR /src

COPY . /src/

# hadolint ignore=DL3008 We want the latest stable versions
RUN apk update && apk upgrade \
&& \
apk add --no-cache \
bsd-compat-headers \
cmake \
file \
g++ \
libtool \
linux-headers \
make \
musl-fts-dev \
# Clamav dependencies provided by alpine
bzip2-dev \
check-dev \
curl-dev \
json-c-dev \
libmilter-dev \
libxml2-dev \
ncurses-dev \
ncurses-dev \
openssl-dev \
pcre2-dev \
zlib-dev \
# For the tests
python3 \
py3-pytest \
# For Rust/Cargo
cargo \
rust \
&& \
mkdir -p "./build" && cd "./build" && \
cmake .. \
-D CMAKE_BUILD_TYPE="Release" \
-D CMAKE_INSTALL_PREFIX="/usr" \
-D CMAKE_INSTALL_LIBDIR="/usr/lib" \
-D APP_CONFIG_DIRECTORY="/etc/clamav" \
-D DATABASE_DIRECTORY="/var/lib/clamav" \
-D ENABLE_CLAMONACC=OFF \
-D ENABLE_EXAMPLES=OFF \
-D ENABLE_MILTER=ON \
-D ENABLE_MAN_PAGES=OFF \
-D ENABLE_STATIC_LIB=OFF \
-D ENABLE_JSON_SHARED=ON \
&& \
make DESTDIR="/clamav" -j$(($(nproc) - 1)) install && \
rm -r \
"/clamav/usr/lib/pkgconfig/" \
&& \
sed -e "s|^\(Example\)|\# \1|" \
-e "s|.*\(PidFile\) .*|\1 /tmp/clamd.pid|" \
-e "s|.*\(LocalSocket\) .*|\1 /tmp/clamd.sock|" \
-e "s|.*\(TCPSocket\) .*|\1 3310|" \
-e "s|.*\(TCPAddr\) .*|#\1 0.0.0.0|" \
-e "s|.*\(User\) .*|\1 clamav|" \
-e "s|^\#\(LogFile\) .*|\1 /var/log/clamav/clamd.log|" \
-e "s|^\#\(LogTime\).*|\1 yes|" \
"/clamav/etc/clamav/clamd.conf.sample" > "/clamav/etc/clamav/clamd.conf" && \
sed -e "s|^\(Example\)|\# \1|" \
-e "s|.*\(PidFile\) .*|\1 /tmp/freshclam.pid|" \
-e "s|.*\(DatabaseOwner\) .*|\1 clamav|" \
-e "s|^\#\(UpdateLogFile\) .*|\1 /var/log/clamav/freshclam.log|" \
-e "s|^\#\(NotifyClamd\).*|\1 /etc/clamav/clamd.conf|" \
-e "s|^\#\(ScriptedUpdates\).*|\1 yes|" \
"/clamav/etc/clamav/freshclam.conf.sample" > "/clamav/etc/clamav/freshclam.conf" && \
sed -e "s|^\(Example\)|\# \1|" \
-e "s|.*\(PidFile\) .*|\1 /tmp/clamav-milter.pid|" \
-e "s|.*\(MilterSocket\) .*|\1 inet:7357|" \
-e "s|.*\(User\) .*|\1 clamav|" \
-e "s|^\#\(LogFile\) .*|\1 /var/log/clamav/milter.log|" \
-e "s|^\#\(LogTime\).*|\1 yes|" \
-e "s|.*\(\ClamdSocket\) .*|\1 unix:/tmp/clamd.sock|" \
"/clamav/etc/clamav/clamav-milter.conf.sample" > "/clamav/etc/clamav/clamav-milter.conf" || \
exit 1 \
&& \
ctest -V

FROM index.docker.io/library/alpine:latest

LABEL maintainer="ClamAV bugs <[email protected]>"

EXPOSE 3310
EXPOSE 7357

ENV TZ Etc/UTC

RUN apk add --no-cache \
fts \
libstdc++ \
tini \
tzdata \
# Clamav dependencies provided by alpine
json-c \
libbz2 \
libcurl \
libmilter \
libxml2 \
ncurses-libs \
pcre2 \
zlib \
&& \
addgroup -S "clamav" && \
adduser -D -G "clamav" -h "/var/lib/clamav" -s "/bin/false" -u 100 -S "clamav" && \
install -d -m 755 -g "clamav" -o "clamav" "/var/log/clamav" && \
chown -R clamav:clamav /var/lib/clamav

COPY --from=builder "/clamav" "/"
COPY "./scripts/clamdcheck.sh" "/usr/local/bin/"
COPY "./scripts/docker-entrypoint.sh" "/init"
COPY "./scripts/docker-entrypoint-unprivileged.sh" "/init-unprivileged"

HEALTHCHECK --start-period=6m CMD clamdcheck.sh

ENTRYPOINT [ "/init" ]
176 changes: 176 additions & 0 deletions clamav/1.4/alpine/Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
properties([
parameters([
string(name: 'DOCKER_REGISTRY', defaultValue: 'registry.hub.docker.com', description: 'The Docker registry to use'),
string(name: 'REGISTRY_CREDS', defaultValue: 'dockerhub', description: 'The Jenkins credentials ID for the given registry'),
string(name: 'WEBEX_SPACE_ID', defaultValue: 'b204c1a0-6862-11e8-9dbc-93ef3cfef186', description: 'ID of Webex space to push pass/fail notifications'),
string(name: 'NAMESPACE', defaultValue: 'clamav', description: 'The docker namespace to use'),
string(name: 'IMAGE_NAME', defaultValue: 'clamav', description: 'The docker image name to use'),
string(name: 'REPOSITORY', defaultValue: 'https://github.com/Cisco-Talos/clamav.git', description: 'The repository from which to build'),
string(name: 'BRANCH', defaultValue: 'rel/1.4', description: 'The repository branch for this build'),
string(name: 'FULL_VERSION', defaultValue: '1.4.0', description: 'Full version in X.Y.Z format'),
string(name: 'FEATURE_VERSION', defaultValue: '1.4', description: 'Feature version in X.Y format'),
booleanParam(name: 'IS_LATEST', defaultValue: true, description: 'If "true", will also publish to :latest, and :stable tags.'),
]),
disableConcurrentBuilds(),
buildDiscarder(logRotator(
artifactDaysToKeepStr: '10',
artifactNumToKeepStr: '10',
daysToKeepStr: '30',
numToKeepStr: '20'))
])

node('docker') {
cleanWs()

try {
// Checkout the ClamAV source code
checkout([
$class: 'GitSCM', branches: [[name: "${params.BRANCH}"]],
doGenerateSubmoduleConfigurations: false,
extensions: [
[$class: 'RelativeTargetDirectory', relativeTargetDir: '.'],
[$class: 'CloneOption', depth: 1, noTags: false, reference: '', shallow: true]
],
submoduleCfg: [], userRemoteConfigs: [[url: "${params.REPOSITORY}"]]
])

// Remove the Dockerfile and scripts from the clamav repo, if any.
sh """
rm -rf ./Dockerfile ./dockerfiles
"""

// Checkout the current repo
dir(path: 'clamav-docker') {
checkout scm
}

// Use the Dockerfile and scripts from this repo.
sh """
cp -r clamav-docker/clamav/${params.FEATURE_VERSION}/alpine/Dockerfile clamav-docker/clamav/${params.FEATURE_VERSION}/alpine/scripts .
"""

stage('Build Image') {
withVault([vaultSecrets: [[ path: "clamavbuild-kv/${params.REGISTRY_CREDS}", engineVersion: 1, secretValues:
[[envVar: 'DOCKER_USER', vaultKey: 'username'],[envVar: 'DOCKER_PASSWD', vaultKey: 'password']]]]]) {
// Make sure we have the latest base image.
sh """
docker pull alpine:latest
"""

// Login to docker hub
sh """
echo "\${_passwd:-\${DOCKER_PASSWD}}" | \
docker login --password-stdin --username "${DOCKER_USER}" "${params.DOCKER_REGISTRY}"
"""

//
// Build the following images:
// - X.Y.Z-R, X.Y.Z-R_base
// - X.Y.Z, X.Y.Z_base
// - X.Y, X.Y_base
//
// And maybe also:
// - latest, latest_base
// - stable, stable_base
//

// Build X.Y.Z-R_base image.
sh """
docker build --no-cache --tag "${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER}_base" .
"""

// Publish X.Y.Z-R_base tag
sh """
docker image tag ${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER}_base ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER}_base
docker image push ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER}_base
"""

// Publish X.Y.Z_base tag
sh """
docker image tag ${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER}_base ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FULL_VERSION}_base
docker image push ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FULL_VERSION}_base
"""

// Publish X.Y_base tag
sh """
docker image tag ${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER}_base ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FEATURE_VERSION}_base
docker image push ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FEATURE_VERSION}_base
"""

if (params.IS_LATEST) {
// Create & Publish 'stable_base' and 'latest_base' tags.
sh """
docker image tag ${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER}_base ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:stable_base
docker image push ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:stable_base
docker image tag ${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER}_base ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:latest_base
docker image push ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:latest_base
"""
}

// The update_db_image.sh script will query for tags during the update process.
// So give the registry a little time to add the X.Y.Z-R_base image.
sh """
sleep 20
"""

// Pull the X.Y.Z-R_base image, update the DB, and push it out as X.Y.Z-R (without the _base suffix)
sh """
DOCKER_REGISTRY="${params.DOCKER_REGISTRY}" \
CLAMAV_DOCKER_IMAGE="${params.IMAGE_NAME}" \
./scripts/update_db_image.sh -t ${params.FULL_VERSION}-${BUILD_NUMBER}_base -n ${params.NAMESPACE}
"""

// Login to docker hub again, because the update_db_image.sh script removed our creds in its cleanup stage
sh """
echo "\${_passwd:-\${DOCKER_PASSWD}}" | \
docker login --password-stdin --username "${DOCKER_USER}" "${params.DOCKER_REGISTRY}"
"""

// Publish X.Y.Z tag (without the _base suffix)
sh """
docker image tag ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER} ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FULL_VERSION}
docker image push ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FULL_VERSION}
"""

// Publish X.Y tag (without the _base suffix)
sh """
docker image tag ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER} ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FEATURE_VERSION}
docker image push ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FEATURE_VERSION}
"""

if (params.IS_LATEST) {
// Create & Publish 'stable' and 'latest' tags.
sh """
docker image tag ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER} ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:stable
docker image push ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:stable
docker image tag ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:${params.FULL_VERSION}-${BUILD_NUMBER} ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:latest
docker image push ${params.DOCKER_REGISTRY}/${params.NAMESPACE}/${params.IMAGE_NAME}:latest
"""
}

// log-out (again)
sh """
docker logout "${params.DOCKER_REGISTRY}"
"""
}
}

} catch(err) {
// log-out, if required
sh """
docker logout "${params.DOCKER_REGISTRY}" || true
"""

currentBuild.result = "FAILED"
sparkSend(
message: "Docker build of ${params.FULL_VERSION} from ${params.REPOSITORY} branch ${params.BRANCH} for ${params.NAMESPACE}/${params.IMAGE_NAME} [FAILED](${BUILD_URL})",
spaceList: [[spaceName: "ClamAV Jenkins", spaceId: "${params.WEBEX_SPACE_ID}"]], credentialsId: 'clambuilder', messageType: 'markdown')
throw err
}

sparkSend(
message: "Docker build of ${params.FULL_VERSION} from ${params.REPOSITORY} branch ${params.BRANCH} for ${params.NAMESPACE}/${params.IMAGE_NAME} [PASSED](${BUILD_URL})",
spaceList: [[spaceName: "ClamAV Jenkins", spaceId: "${params.WEBEX_SPACE_ID}"]], credentialsId: 'clambuilder', messageType: 'markdown')
}
14 changes: 14 additions & 0 deletions clamav/1.4/alpine/scripts/clamdcheck.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

set -eu

if [ "${CLAMAV_NO_CLAMD:-}" != "false" ]; then
if [ "$(echo "PING" | nc localhost 3310)" != "PONG" ]; then
echo "ERROR: Unable to contact server"
exit 1
fi

echo "Clamd is up"
fi

exit 0
72 changes: 72 additions & 0 deletions clamav/1.4/alpine/scripts/docker-entrypoint-unprivileged.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/sbin/tini /bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright (C) 2021 Olliver Schinagl <[email protected]>
# Copyright (C) 2021-2023 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
#
# A beginning user should be able to docker run image bash (or sh) without
# needing to learn about --entrypoint
# https://github.com/docker-library/official-images#consistency

set -eu

# run command if it is not starting with a "-" and is an executable in PATH
if [ "${#}" -gt 0 ] && \
[ "${1#-}" = "${1}" ] && \
command -v "${1}" > "/dev/null" 2>&1; then
# Ensure healthcheck always passes
CLAMAV_NO_CLAMD="true" exec "${@}"
else
if [ "${#}" -ge 1 ] && \
[ "${1#-}" != "${1}" ]; then
# If an argument starts with "-" pass it to clamd specifically
exec clamd "${@}"
fi
# else default to running clamav's servers

# Ensure we have some virus data, otherwise clamd refuses to start
if [ ! -f "/var/lib/clamav/main.cvd" ]; then
echo "Updating initial database"
freshclam --foreground --stdout
fi

if [ "${CLAMAV_NO_FRESHCLAMD:-false}" != "true" ]; then
echo "Starting Freshclamd"
freshclam \
--checks="${FRESHCLAM_CHECKS:-1}" \
--daemon \
--foreground \
--stdout \
--user="clamav" \
&
fi

if [ "${CLAMAV_NO_CLAMD:-false}" != "true" ]; then
echo "Starting ClamAV"
if [ -S "/tmp/clamd.sock" ]; then
unlink "/tmp/clamd.sock"
fi
clamd --foreground &
while [ ! -S "/tmp/clamd.sock" ]; do
if [ "${_timeout:=0}" -gt "${CLAMD_STARTUP_TIMEOUT:=1800}" ]; then
echo
echo "Failed to start clamd"
exit 1
fi
printf "\r%s" "Socket for clamd not found yet, retrying (${_timeout}/${CLAMD_STARTUP_TIMEOUT}) ..."
sleep 1
_timeout="$((_timeout + 1))"
done
echo "socket found, clamd started."
fi

if [ "${CLAMAV_NO_MILTERD:-true}" != "true" ]; then
echo "Starting clamav milterd"
clamav-milter &
fi

# Wait forever (or until canceled)
exec tail -f "/dev/null"
fi

exit 0
Loading

0 comments on commit 4b79cb9

Please sign in to comment.