-
Notifications
You must be signed in to change notification settings - Fork 105
Expand file tree
/
Copy pathbootstrap.sh
More file actions
executable file
·215 lines (178 loc) · 7.41 KB
/
Copy pathbootstrap.sh
File metadata and controls
executable file
·215 lines (178 loc) · 7.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
CMD="$(basename "$0")"
function Log {
case "$1" in
(INFO|WARNING|ERROR) SEVERITY="$1" ;;
(*) SEVERITY=INFO ;;
esac
FUNCTION="$2"
MESSAGE="$3"
cat <<EOF
{"severity": "${SEVERITY}", "message": "${CMD}: ${MESSAGE}", "logging.googleapis.com/sourceLocation": {"file": "${CMD}", "function": "${FUNCTION}"}}
EOF
}
# Exit immediately on error.
function trapError {
Log ERROR main "command returned error status, exiting"
exit 1
}
trap trapError ERR
# Setup config
CONFIG_FILE=./config.json
# Check for config from environment
#
if [[ "${CONFIG_JSON}" ]] ; then
Log INFO main "Using config from environment variable CONFIG_JSON"
echo "${CONFIG_JSON}" > ${CONFIG_FILE}
fi
# Check and perform shell-variable substitution on config file, copying it to /etc
#
Log INFO main "Perfoming env var substitution on config file"
if [[ ! -e "${CONFIG_FILE}" ]] ; then
Log ERROR main "${CONFIG_FILE} does not exist"
exit 1
fi
envsubst < "${CONFIG_FILE}" > /etc/malware-scanner-config.json
CONFIG_FILE=/etc/malware-scanner-config.json
# Get name of CVD Mirror bucket from config file
#
Log INFO main "Checking ClamCvdMirrorBucket from config file"
CVD_MIRROR_BUCKET=$(/usr/bin/jq -r '.ClamCvdMirrorBucket' "${CONFIG_FILE}")
if [[ -z "${CVD_MIRROR_BUCKET}" || "${CVD_MIRROR_BUCKET}" = "null" ]] ; then
Log ERROR main "ClamCvdMirrorBucket is not defined in ${CONFIG_FILE}"
exit 1
fi
# Start the reverse proxy which adds authentication
# to requests to GCS REST API, allowing freshclam to access the GCS
# CVD mirror bucket as if it was an unauthenticated HTTP server
#
export PROXY_PORT=${PROXY_PORT:-8888}
PROXY_SERVER_ADDRESS=localhost:${PROXY_PORT}
npm run start-proxy "${CONFIG_FILE}" &
# This function is used to update clam and freshclam config files.
# Use by specifying the config file on the command line and
# piping the config file updates in.
#
# Note: clamav takes the _first_ config value found in the file, so first
# remove any existing values for the parameters defined in the update, then
# append the new values.
#
function updateClamConfigFile {
CLAM_CONFIG_FILE=$1
UPDATE_TMPFILE="$(mktemp)"
CLAM_CONFIG_TMPFILE="$(mktemp)"
cat > "${UPDATE_TMPFILE}"
# Find modified parameters in update, and emit a '|' separated list.
MODIFIED_PARAMS=$(gawk '! /^\s*#/ && /^\S+\s/ { params=params "|" $1; i++; } END { print substr(params,2) }' "${UPDATE_TMPFILE}")
# Remove lines starting with modified parameter names followed by whitespace
grep -vE "^(XXXXXXXXXX|${MODIFIED_PARAMS})\s" "${CLAM_CONFIG_FILE}" > "${CLAM_CONFIG_TMPFILE}"
# Append updates
cat "${UPDATE_TMPFILE}" >> "${CLAM_CONFIG_TMPFILE}"
mv "${CLAM_CONFIG_TMPFILE}" "${CLAM_CONFIG_FILE}"
chmod go+r "${CLAM_CONFIG_FILE}"
Log INFO updateClamConfigFile "Updated ${CLAM_CONFIG_FILE} with parameters: ${MODIFIED_PARAMS}"
}
Log INFO main "Updating ClamAV config files"
# Get value for ClamD conf AlertEncrypted from config file
# Translate json truthy value to yes/no, defaulting to yes if not specified.
ALERT_ENCRYPTED=$(/usr/bin/jq -r '.quarantine.encryptedFiles' "${CONFIG_FILE}")
case "${ALERT_ENCRYPTED}" in
"true"|"1"|"null"|""|"yes") ALERT_ENCRYPTED=yes;;
"false"|"0"|"no") ALERT_ENCRYPTED=no;;
*)
Log ERROR main "Invalid value '${ALERT_ENCRYPTED}' for quarantine.encryptedFiles in ${CONFIG_FILE}"
exit 1
;;
esac
# Set Clam config file values
# see clamd.conf documentation:
# https://manpages.debian.org/bullseye/clamav-daemon/clamd.conf.5.en.html
updateClamConfigFile /etc/clamav/clamd.conf << EOF
# This option allows you to specify the upper limit for data size that will be transferred to remote daemon when scanning a single file.
StreamMaxLength 512M
# Sets the maximum amount of data to be scanned for each input file.
# Archives and other containers are recursively extracted and scanned up to this value.
MaxScanSize 512M
# Files larger than this limit won't be scanned.
# Affects the input file itself as well as files contained inside it (when the input file is an archive, a document or some other kind of container).
MaxFileSize 512M
# Nested archives are scanned recursively, e.g. if a Zip archive contains a RAR file, all files within it will also be scanned.
# This options specifies how deeply the process should be continued.
MaxRecursion 16
# Number of files to be scanned within an archive, a document, or any other kind of container.
MaxFiles 10000
# Port and bind address for clamav daemon
TCPSocket 3310
TCPAddr 127.0.0.1
# Always consider encrypted/password protected files as infected.
AlertEncrypted ${ALERT_ENCRYPTED}
EOF
# Update Freshclam config values
# see freshclam.conf documentation:
# https://manpages.debian.org/bullseye/clamav-freshclam/freshclam.conf.5.en.html
updateClamConfigFile /etc/clamav/freshclam.conf << EOF
# DatabaseMirror specifies to which mirror(s) freshclam should connect.
# Set to the authentication proxy service which proxys to the GCS API.
DatabaseMirror http://${PROXY_SERVER_ADDRESS}/${CVD_MIRROR_BUCKET}/cvds
# Number of database checks per day.
# Once per half hour, which is fine as we are using a local mirror.
# overridden by command line --checks=\$FRESHCLAM_CHECKS
Checks 48
EOF
function waitForAlive() {
if [[ "$#" -lt 4 ]] ; then
echo "waitForAlive name interval attempts alive-check-command"
return 1
fi
local -r CHECK_NAME="$1"
local -i -r CHECK_INTERVAL="$2"
local -i -r CHECK_ATTEMPTS="$3"
shift ; shift ; shift
local -i attempts=0
while [[ $attempts -lt "${CHECK_ATTEMPTS}" ]]; do
attempts=$((attempts + 1))
Log INFO main "Waiting for $CHECK_NAME to start...${attempts}"
sleep ${CHECK_INTERVAL}
# run alive check...
"${@}" >& /dev/null && break
done
if [[ $attempts -eq ${CHECK_ATTEMPTS} ]] ; then
Log ERROR main "$CHECK_NAME did not start after $((CHECK_ATTEMPTS * CHECK_INTERVAL)) secs"
exit 1;
fi
}
# Allow 1 min for proxy server to start up.
# Use a request to get the state.json to verify the proxy is alive and proxying.
waitForAlive "Proxy server" "${PROXY_CHECK_INTERVAL:-5}" "${PROXY_CHECK_ATTEMPTS:-12}" \
curl -s -I "http://${PROXY_SERVER_ADDRESS}/${CVD_MIRROR_BUCKET}/cvds/state.json"
# Restart clamav and freshclam Services
Log INFO main "Starting clamav services"
# Ensure correct services are started:
# https://github.com/Cisco-Talos/clamav-docker/blob/main/clamav/README-debian.md#controlling-the-container
# Note -- double-negative variables.
CLAMAV_NO_CLAMD=false
CLAMAV_NO_FRESHCLAMD=false
CLAMAV_NO_MILTERD=true
FRESHCLAM_CHECKS=48 # 48/day = every half hour.
export CLAMAV_NO_CLAMD CLAMAV_NO_FRESHCLAMD CLAMAV_NO_MILTERD FRESHCLAM_CHECKS
/init &
sleep 30
# Allow another 2 min for clamd service to start up.
waitForAlive "Clamd service" "${CLAMD_CHECK_INTERVAL:-10}" "${CLAMD_CHECK_ATTEMPTS:-12}" \
clamdcheck.sh
# Run node server process
Log INFO main "Starting malware-scanner service"
exec npm run start "${CONFIG_FILE}"