-
Notifications
You must be signed in to change notification settings - Fork 6
/
generate_ossec.sh
executable file
·493 lines (424 loc) · 15.7 KB
/
generate_ossec.sh
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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
#!/bin/bash
# Program to build and sign debian packages, and upload those to a public reprepro repository.
# Copyright (c) 2015 Santiago Bassett <[email protected]>
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
# CONFIGURATION VARIABLES
#
ossec_version='2.8.2'
source_file="ossec-hids-${ossec_version}.tar.gz"
#packages=(ossec-hids ossec-hids-agent) # only options available
packages=(ossec-hids ossec-hids-agent)
# codenames=(sid jessie wheezy precise trusty utopic)
codenames=(sid jessie wheezy precise trusty utopic)
# For Debian use: sid, jessie or wheezy (hardcoded in update_changelog function)
# For Ubuntu use: lucid, precise, trusty or utopic
codenames_ubuntu=(precise trusty utopic)
codenames_debian=(sid jessie wheezy)
# architectures=(amd64 i386) only options available
architectures=(amd64 i386)
# GPG key
signing_key='XXXX'
signing_pass='XXXX'
# Debian files
debian_files_path="/home/ubuntu/debian_files"
# Setting up logfile
scriptpath=$( cd $(dirname $0) ; pwd -P )
logfile=$scriptpath/ossec_packages.log
#
# Function to write to LOG_FILE
#
write_log()
{
if [ ! -e "$logfile" ] ; then
touch "$logfile"
fi
while read text
do
local logtime=`date "+%Y-%m-%d %H:%M:%S"`
echo $logtime": $text" | tee -a $logfile;
done
}
#
# Check if element is in an array
# Arguments: element array
#
contains_element() {
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
#
# Show help function
#
show_help()
{
echo "
This tool can be used to generate OSSEC packages for Ubuntu and Debian.
CONFIGURATION: The script is currently configured with the following variables:
* Packages: ${packages[*]}.
* Distributions: ${codenames[*]}.
* Architectures: ${architectures[*]}.
* OSSEC version: ${ossec_version}.
* Source file: ${source_file}.
* Signing key: ${signing_key}.
USAGE: Command line arguments available:
-h | --help Displays this help.
-u | --update Updates chroot environments.
-d | --download Downloads source file and prepares source directories.
-b | --build Builds deb packages.
-s | --sync Synchronizes with the apt-get repository.
"
}
#
# Reads latest package version from changelog file
# Argument: changelog_file
#
read_package_version()
{
if [ ! -e "$1" ] ; then
echo "Error: Changelog file $1 does not exist" | write_log
exit 1
fi
local regex="^ossec-hids[A-Za-z-]* \([0-9]+.*[0-9]*.*[0-9]*-([0-9]+)[A-Za-z]*\)"
while read line
do
if [[ $line =~ $regex ]]; then
package_version="${BASH_REMATCH[1]}"
break
fi
done < $1
local check_regex='^[0-9]+$'
if ! [[ ${package_version} =~ ${check_regex} ]]; then
echo "Error: Package version could not be read from $1" | write_log
exit 1
fi
}
#
# Updates changelog file with new codename, date and debdist.
# Arguments: changelog_file codename
#
update_changelog()
{
local changelog_file=$1
local changelog_file_tmp="${changelog_file}.tmp"
local codename=$2
if [ ! -e "$1" ] ; then
echo "Error: Changelog file $1 does not exist" | write_log
exit 1
fi
local check_codenames=( ${codenames_debian[*]} ${codenames_ubuntu[*]} )
if ! contains_element $codename ${check_codenames[*]} ; then
echo "Error: Codename $codename not contained in codenames for Debian or Ubuntu" | write_log
exit 1
fi
# For Debian
if [ $codename = "sid" ]; then
local debdist="unstable"
elif [ $codename = "jessie" ]; then
local debdist="testing"
elif [ $codename = "wheezy" ]; then
local debdist="stable"
fi
# For Ubuntu
if contains_element $codename ${codenames_ubuntu[*]} ; then
local debdist=$codename
fi
# Modifying file
local changelogtime=$(date -R)
local last_date_changed=0
local regex1="^(ossec-hids[A-Za-z-]* \([0-9]+.*[0-9]*.*[0-9]*-[0-9]+)[A-Za-z]*\)"
local regex2="( -- [[:alnum:]]*[^>]*> )[[:alnum:]]*,"
if [ -f ${changelog_file_tmp} ]; then
rm -f ${changelog_file_tmp}
fi
touch ${changelog_file_tmp}
IFS='' #To preserve line leading whitespaces
while read line
do
if [[ $line =~ $regex1 ]]; then
line="${BASH_REMATCH[1]}$codename) $debdist; urgency=low"
fi
if [[ $line =~ $regex2 ]] && [ $last_date_changed -eq 0 ]; then
line="${BASH_REMATCH[1]}$changelogtime"
last_date_changed=1
fi
echo "$line" >> ${changelog_file_tmp}
done < ${changelog_file}
mv ${changelog_file_tmp} ${changelog_file}
}
#
# Update chroot environments
#
update_chroots()
{
for codename in ${codenames[@]}
do
for arch in ${architectures[@]}
do
echo "Updating chroot environment: ${codename}-${arch}" | write_log
if sudo DIST=$codename ARCH=$arch pbuilder update ; then
echo "Successfully updated chroot environment: ${codename}-${arch}" | write_log
else
echo "Error: Problem detected updating chroot environment: ${codename}-${arch}" | write_log
fi
done
done
}
#
# Downloads packages and prepare source directories.
# This is needed before building the packages.
#
download_source()
{
# Checking that Debian files exist for this version
for package in ${packages[*]}
do
if [ ! -d ${debian_files_path}/${ossec_version}/$package/debian ]; then
echo "Error: Couldn't find debian files directory for $package, version ${ossec_version}" | write_log
exit 1
fi
done
# Downloading file
if wget -O $scriptpath/${source_file} -U ossec https://github.com/ossec/ossec-hids/archive/${ossec_version}.tar.gz ; then
echo "Successfully downloaded source file ${source_file} from ossec.net" | write_log
else
echo "Error: File ${source_file} was could not be downloaded" | write_log
exit 1
fi
# Uncompressing files
tmp_directory=$(echo ${source_file} | sed -e 's/.tar.gz$//')
if [ -d ${scriptpath}/${tmp_directory} ]; then
echo " + Deleting previous directory ${scriptpath}/${tmp_directory}" | write_log
sudo rm -rf ${scriptpath}/${tmp_directory}
fi
tar -xvzf ${scriptpath}/${source_file}
if [ ! -d ${scriptpath}/${tmp_directory} ]; then
echo "Error: Couldn't find uncompressed directory, named ${tmp_directory}" | write_log
exit 1
fi
# Organizing directories structure
for package in ${packages[*]}
do
if [ -d ${scriptpath}/$package ]; then
echo " + Deleting previous source directory ${scriptpath}/$package" | write_log
sudo rm -rf ${scriptpath}/$package
fi
mkdir $scriptpath/$package
cp -pr $scriptpath/${tmp_directory} $scriptpath/$package/$package-${ossec_version}
cp -p $scriptpath/${source_file} $scriptpath/$package/${package}_${ossec_version}.orig.tar.gz
cp -pr ${debian_files_path}/${ossec_version}/$package/debian $scriptpath/$package/${package}-${ossec_version}/debian
done
rm -rf $scriptpath/${tmp_directory}
echo "The packages directories for ${packages[*]} version ${ossec_version} have been successfully prepared." | write_log
}
#
# Build packages
#
build_packages()
{
for package in ${packages[@]}
do
for codename in ${codenames[@]}
do
for arch in ${architectures[@]}
do
echo "Building Debian package ${package} ${codename}-${arch}" | write_log
local source_path="$scriptpath/${package}/${package}-${ossec_version}"
local changelog_file="${source_path}/debian/changelog"
if [ ! -f ${changelog_file} ] ; then
echo "Error: Couldn't find changelog file for ${package}-${ossec_version}" | write_log
exit 1
fi
# Updating changelog file with new codename, date and debdist.
if update_changelog ${changelog_file} ${codename} ; then
echo " + Changelog file ${changelog_file} updated for $package ${codename}-${arch}" | write_log
else
echo "Error: Changelog file ${changelog_file} for $package ${codename}-${arch} could not be updated" | write_log
exit 1
fi
# Setting up global variable package_version, used for deb_file and changes_file
read_package_version ${changelog_file}
local deb_file="${package}_${ossec_version}-${package_version}${codename}_${arch}.deb"
local changes_file="${package}_${ossec_version}-${package_version}${codename}_${arch}.changes"
local dsc_file="${package}_${ossec_version}-${package_version}${codename}.dsc"
local results_dir="/var/cache/pbuilder/${codename}-${arch}/result/${package}"
local base_tgz="/var/cache/pbuilder/${codename}-${arch}-base.tgz"
local cache_dir="/var/cache/pbuilder/${codename}-${arch}/aptcache"
# Creating results directory if it does not exist
if [ ! -d ${results_dir} ]; then
sudo mkdir -p ${results_dir}
fi
# Building the package
cd ${source_path}
if sudo /usr/bin/pdebuild --use-pdebuild-internal --architecture ${arch} --buildresult ${results_dir} -- --basetgz \
${base_tgz} --distribution ${codename} --architecture ${arch} --aptcache ${cache_dir} --override-config ; then
echo " + Successfully built Debian package ${package} ${codename}-${arch}" | write_log
else
echo "Error: Could not build package $package ${codename}-${arch}" | write_log
exit 1
fi
# Checking that resulting debian package exists
if [ ! -f ${results_dir}/${deb_file} ] ; then
echo "Error: Could not find ${results_dir}/${deb_file}" | write_log
exit 1
fi
# Checking that package has at least 50 files to confirm it has been built correctly
local files=$(sudo /usr/bin/dpkg --contents ${results_dir}/${deb_file} | wc -l)
if [ "${files}" -lt "50" ]; then
echo "Error: Package ${package} ${codename}-${arch} contains only ${files} files" | write_log
echo "Error: Check that the Debian package has been built correctly" | write_log
exit 1
else
echo " + Package ${results_dir}/${deb_file} ${codename}-${arch} contains ${files} files" | write_log
fi
# Signing Debian package
if [ ! -f "${results_dir}/${changes_file}" ] || [ ! -f "${results_dir}/${dsc_file}" ] ; then
echo "Error: Could not find dsc and changes file in ${results_dir}" | write_log
exit 1
fi
sudo /usr/bin/expect -c "
spawn sudo debsign --re-sign -k${signing_key} ${results_dir}/${changes_file}
expect -re \".*Enter passphrase:.*\"
send \"${signing_pass}\r\"
expect -re \".*Enter passphrase:.*\"
send \"${signing_pass}\r\"
expect -re \".*Successfully signed dsc and changes files.*\"
"
if [ $? -eq 0 ] ; then
echo " + Successfully signed Debian package ${changes_file} ${codename}-${arch}" | write_log
else
echo "Error: Could not sign Debian package ${changes_file} ${codename}-${arch}" | write_log
exit 1
fi
# Verifying signed changes and dsc files
if sudo gpg --verify "${results_dir}/${dsc_file}" && sudo gpg --verify "${results_dir}/${changes_file}" ; then
echo " + Successfully verified GPG signature for files ${dsc_file} and ${changes_file}" | write_log
else
echo "Error: Could not verify GPG signature for ${dsc_file} and ${changes_file}" | write_log
exit 1
fi
echo "Successfully built and signed Debian package ${package} ${codename}-${arch}" | write_log
done
done
done
}
# Synchronizes with the external repository, uploading new packages and ubstituting old ones.
sync_repository()
{
for package in ${packages[@]}
do
for codename in ${codenames[@]}
do
for arch in ${architectures[@]}
do
# Reading package version from changelog file
local source_path="$scriptpath/${package}/${package}-${ossec_version}"
local changelog_file="${source_path}/debian/changelog"
if [ ! -f ${changelog_file} ] ; then
echo "Error: Couldn't find ${changelog_file} for package ${package} ${codename}-${arch}" | write_log
exit 1
fi
# Setting up global variable package_version, used for deb_file and changes_file.
read_package_version ${changelog_file}
local deb_file="${package}_${ossec_version}-${package_version}${codename}_${arch}.deb"
local changes_file="${package}_${ossec_version}-${package_version}${codename}_${arch}.changes"
local results_dir="/var/cache/pbuilder/${codename}-${arch}/result/${package}"
if [ ! -f ${results_dir}/${deb_file} ] || [ ! -f ${results_dir}/${changes_file} ] ; then
echo "Error: Coudn't find ${deb_file} or ${changes_file}" | write_log
exit 1
fi
# Uploading package to repository
cd ${results_dir}
echo "Uploading package ${changes_file} for ${codename} to OSSEC repository" | write_log
if sudo /usr/bin/dupload --nomail -f --to ossec-repository ${changes_file} ; then
echo " + Successfully uploaded package ${changes_file} for ${codename} to OSSEC repository" | write_log
else
echo "Error: Could not upload package ${changes_file} for ${codename} to the repository" | write_log
exit 1
fi
# Checking if it is an Ubuntu package
if contains_element $codename ${codenames_ubuntu[*]} ; then
local is_ubuntu=1
else
local is_ubuntu=0
fi
# Moving package to the right directory at the OSSEC apt repository server
echo " + Adding package /opt/incoming/${deb_file} to server repository for ${codename} distribution" | write_log
if [ $is_ubuntu -eq 1 ]; then
remove_package="cd /var/www/repos/apt/ubuntu; reprepro -A ${arch} remove ${codename} ${package}"
include_package="cd /var/www/repos/apt/ubuntu; reprepro includedeb ${codename} /opt/incoming/${deb_file}"
else
remove_package="cd /var/www/repos/apt/debian; reprepro -A ${arch} remove ${codename} ${package}"
include_package="cd /var/www/repos/apt/debian; reprepro includedeb ${codename} /opt/incoming/${deb_file}"
fi
/usr/bin/expect -c "
spawn sudo ssh root@ossec-repository \"${remove_package}\"
expect -re \"Not removed as not found.*\" { exit 1 }
expect -re \".*enter passphrase:.*\" { send \"${signing_pass}\r\" }
expect -re \".*enter passphrase:.*\" { send \"${signing_pass}\r\" }
expect -re \".*deleting.*\"
"
/usr/bin/expect -c "
spawn sudo ssh root@ossec-repository \"${include_package}\"
expect -re \"Skipping inclusion.*\" { exit 1 }
expect -re \".*enter passphrase:.*\"
send \"${signing_pass}\r\"
expect -re \".*enter passphrase:.*\"
send \"${signing_pass}\r\"
expect -re \".*Exporting.*\"
"
echo "Successfully added package ${deb_file} to server repository for ${codename} distribution" | write_log
done
done
done
}
# If there are no arguments, display help
if [ $# -eq 0 ]; then
show_help
exit 0
fi
# Reading command line arguments
while [[ $# > 0 ]]
do
key="$1"
shift
case $key in
-h|--help)
show_help
exit 0
;;
-u|--update)
update_chroots
shift
;;
-d|--download)
download_source
shift
;;
-b|--build)
build_packages
shift
;;
-s|--sync)
sync_repository
shift
;;
*)
echo "Unknown command line argument."
show_help
exit 0
;;
esac
done
# vim: tabstop=2 expandtab shiftwidth=2 softtabstop=2