-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathbuild-vbox.sh
executable file
·344 lines (306 loc) · 12.1 KB
/
build-vbox.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
#!/bin/bash
set -eu
WELL_KNOWN_CACHING_PROXIES="\
3142 apt-cacher-ng
8000 squid-deb-proxy
9999 approx"
DETECTED_CACHING_PROXY=
SUPPORTED_ARCHITECTURES="amd64 i386"
SUPPORTED_BRANCHES="kali-dev kali-last-snapshot kali-rolling"
SUPPORTED_DESKTOPS="e17 gnome headless i3 kde lxde mate xfce"
SUPPORTED_TOOLSETS="default everything large none"
SUPPORTED_FORMATS="ova ovf raw qemu virtualbox vmware"
SUPPORTED_VARIANTS="generic qemu rootfs virtualbox vmware"
DEFAULT_ARCH=amd64
DEFAULT_BRANCH=kali-rolling
DEFAULT_DESKTOP=xfce
DEFAULT_LOCALE=en_US.UTF-8
DEFAULT_MIRROR=http://http.kali.org/kali
DEFAULT_TIMEZONE=Etc/UTC
DEFAULT_TOOLSET=default
DEFAULT_USERPASS=osint:osint
ARCH=
BRANCH=
DESKTOP=
FORMAT=ova
KEEP=false
LOCALE=
MIRROR=
PACKAGES=
PASSWORD=
ROOTFS=
SIZE=40
TIMEZONE=
TOOLSET=
USERNAME=
USERPASS=
VARIANT=virtualbox
VERSION=2023.03
ZIP=true
OUTDIR=images
default_toolset() { [ ${DESKTOP:-$DEFAULT_DESKTOP} = headless ] && echo none || echo default; }
default_version() { echo ${BRANCH:-$DEFAULT_BRANCH} | sed "s/^kali-//"; }
# Output bold only if both stdout/stderr are opened on a terminal
if [ -t 1 -a -t 2 ]; then
b() { tput bold; echo -n "$@"; tput sgr0; }
else
b() { echo -n "$@"; }
fi
warn() { echo "WARNING:" "$@" >&2; }
fail() { echo "ERROR:" "$@" >&2; exit 1; }
kali_message() {
local line=
echo "┏━━($(b $@))"
while IFS= read -r line; do echo "┃ $line"; done
echo "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
ask_confirmation() {
local question=${1:-"Do you want to continue?"}
local default=yes
local default_verbing=
local choices=
local grand_timeout=60
local timeout=20
local time_left=
local answer=
local ret=
# If stdin is closed, no need to ask, assume yes
[ -t 0 ] || return 0
# Set variables that depend on default
if [ $default = yes ]; then
default_verbing=proceeding
choices="[Y/n]"
else
default_verbing=aborting
choices="[y/N]"
fi
# Discard chars pending on stdin
while read -r -t 0; do read -r; done
# Ask the question, allow for X timeouts before proceeding anyway
grand_timeout=$((grand_timeout - timeout))
for time_left in $(seq $grand_timeout -$timeout 0); do
ret=0
read -r -t $timeout -p "$question $choices " answer || ret=$?
if [ $ret -gt 128 ]; then
if [ $time_left -gt 0 ]; then
echo "$time_left seconds left before $default_verbing"
else
echo "No answer, assuming $default, $default_verbing"
fi
continue
elif [ $ret -gt 0 ]; then
exit $ret
else
break
fi
done
# Process the answer
[ "$answer" ] && answer=${answer,,} || answer=$default
case "$answer" in
(y|yes) return 0 ;;
(*) return 1 ;;
esac
}
if [ $(id -u) -eq 0 ]; then
warn "This script does not require root privileges."
warn "Please consider running it as a non-root user."
fi
USAGE="Usage: $(basename $0) [<option>...] [-- <debos option>...]
Build a TL OSINT VM image, base image is Kali Rolling.
Build options:
-a ARCH Build an image for this architecture, default: $(b $DEFAULT_ARCH)
Supported values: $SUPPORTED_ARCHITECTURES
-b BRANCH Kali branch used to build the image, default: $(b $DEFAULT_BRANCH)
Supported values: $SUPPORTED_BRANCHES
-f FORMAT Format to export the image to, default depends on the VARIANT
Supported values: $SUPPORTED_FORMATS
-k Keep raw disk image and other intermediary build artifacts
-m MIRROR Mirror used to build the image, default: $(b $DEFAULT_MIRROR)
-r ROOTFS Rootfs to use to build the image, default: $(b none)
-s SIZE Size of the disk image in GB, default: $(b $SIZE)
-v VARIANT Variant of image to build (see below for details), default: $(b $VARIANT)
Supported values: $SUPPORTED_VARIANTS
-z Zip images and metadata files after the build
Customization options:
-D DESKTOP Desktop environment installed in the image, default: $(b $DEFAULT_DESKTOP)
Supported values: $SUPPORTED_DESKTOPS
-L LOCALE Set locale, default: $(b $DEFAULT_LOCALE)
-P PACKAGES Install extra packages (comma/space separated list)
-S TOOLSET The selection of tools to include in the image, default: $(b $(default_toolset))
Supported values: $SUPPORTED_TOOLSETS
-T TIMEZONE Set timezone, default: $(b $DEFAULT_TIMEZONE)
-U USERPASS Username and password, separated by a colon, default: $(b $DEFAULT_USERPASS)
The different variants of images are:
generic Image with all virtualization support pre-installed, default format: raw
qemu Image with QEMU and SPICE guest agents pre-installed, default format: qemu
rootfs Not an image, a root filesystem (no bootloader/kernel), packed in a .tar.gz
virtualbox Image with VirtualBox guest utilities pre-installed, default format: virtualbox
vmware Image with Open VM Tools pre-installed, default format: vmware
The different formats are:
ova streamOptimized VMDK disk image, OVF metadata file, packed in a OVA archive
ovf monolithicSparse VMDK disk image, OVF metadata file
raw sparse disk image, no metadata
qemu QCOW2 disk image, no metadata
virtualbox VDI disk image, .vbox metadata file
vmware 2GbMaxExtentSparse VMDK disk image, VMX metadata file
Supported environment variables:
http_proxy HTTP proxy URL, refer to the README for more details.
Refer to the README for examples.
"
while getopts ":a:b:D:o:f:hkL:m:P:r:s:S:T:U:v:x:z" opt; do
case $opt in
(a) ARCH=$OPTARG ;;
(b) BRANCH=$OPTARG ;;
(D) DESKTOP=$OPTARG ;;
(o) OUTDIR=$OPTARG ;;
(f) FORMAT=$OPTARG ;;
(h) echo "$USAGE"; exit 0 ;;
(k) KEEP=true ;;
(L) LOCALE=$OPTARG ;;
(m) MIRROR=$OPTARG ;;
(P) PACKAGES="$PACKAGES $OPTARG" ;;
(r) ROOTFS=$OPTARG ;;
(s) SIZE=$OPTARG ;;
(S) TOOLSET=$OPTARG ;;
(T) TIMEZONE=$OPTARG ;;
(U) USERPASS=$OPTARG ;;
(v) VARIANT=$OPTARG ;;
(x) VERSION=$OPTARG ;;
(z) ZIP=true ;;
(*) echo "$USAGE" >&2; exit 1 ;;
esac
done
shift $((OPTIND - 1))
# The first step is to validate the variant.
echo $SUPPORTED_VARIANTS | grep -qw $VARIANT \
|| fail "Unsupported variant '$VARIANT'"
# If format was not set, choose a sensible default according to the variant.
# Moreover, there should be no format when building a rootfs.
if [ $VARIANT != rootfs ]; then
if [ -z "$FORMAT" ]; then
case $VARIANT in
(generic) FORMAT=raw ;;
(qemu) FORMAT=qemu ;;
(virtualbox) FORMAT=virtualbox ;;
(vmware) FORMAT=vmware ;;
(*) fail "Unsupported variant '$VARIANT'" ;;
esac
fi
echo $SUPPORTED_FORMATS | grep -qw $FORMAT \
|| fail "Unsupported format '$FORMAT'"
else
[ -z "$FORMAT" ] || fail "Option -f can't be used to build a rootfs"
fi
# When building an image from an existing rootfs, ARCH and VERSION are picked
# from the rootfs name. Moreover, many options don't apply, as they've been
# set already at the time the rootfs was built.
if [ "$ROOTFS" ]; then
[ $VARIANT != rootfs ] || fail "Option -r can only be used to build images"
[ -z "$ARCH" ] || fail "Option -a can't be used together with option -r"
[ -z "$BRANCH" ] || fail "Option -b can't be used together with option -r"
[ -z "$DESKTOP" ] || fail "Option -D can't be used together with option -r"
[ -z "$LOCALE" ] || fail "Option -L can't be used together with option -r"
[ -z "$MIRROR" ] || fail "Option -m can't be used together with option -r"
[ -z "$TIMEZONE" ] || fail "Option -T can't be used together with option -r"
[ -z "$TOOLSET" ] || fail "Option -S can't be used together with option -r"
[ -z "$USERPASS" ] || fail "Option -U can't be used together with option -r"
[ -z "$VERSION" ] || fail "Option -x can't be used together with option -r"
ARCH=$(basename $ROOTFS | sed "s/\.tar\.gz$//" | rev | cut -d- -f1 | rev)
VERSION=$(basename $ROOTFS | sed -E "s/^rootfs-(.*)-$ARCH\.tar\.gz$/\1/")
else
[ "$ARCH" ] || ARCH=$DEFAULT_ARCH
[ "$BRANCH" ] || BRANCH=$DEFAULT_BRANCH
[ "$DESKTOP" ] || DESKTOP=$DEFAULT_DESKTOP
[ "$LOCALE" ] || LOCALE=$DEFAULT_LOCALE
[ "$MIRROR" ] || MIRROR=$DEFAULT_MIRROR
[ "$TIMEZONE" ] || TIMEZONE=$DEFAULT_TIMEZONE
[ "$TOOLSET" ] || TOOLSET=$(default_toolset)
[ "$USERPASS" ] || USERPASS=$DEFAULT_USERPASS
[ "$VERSION" ] || VERSION=$(default_version)
# Validate some options
echo $SUPPORTED_BRANCHES | grep -qw $BRANCH \
|| fail "Unsupported branch '$BRANCH'"
echo $SUPPORTED_DESKTOPS | grep -qw $DESKTOP \
|| fail "Unsupported desktop '$DESKTOP'"
echo $SUPPORTED_TOOLSETS | grep -qw $TOOLSET \
|| fail "Unsupported toolset '$TOOLSET'"
# Unpack USERPASS to USERNAME and PASSWORD
echo $USERPASS | grep -q ":" \
|| fail "Invalid value for -U, must be of the form '<username>:<password>'"
USERNAME=$(echo $USERPASS | cut -d: -f1)
PASSWORD=$(echo $USERPASS | cut -d: -f2-)
fi
unset USERPASS
# Validate architecture
echo $SUPPORTED_ARCHITECTURES | grep -qw $ARCH \
|| fail "Unsupported architecture '$ARCH'"
# Validate size and add the "GB" suffix
[[ $SIZE =~ ^[0-9]+$ ]] && SIZE=${SIZE}GB \
|| fail "Size must be given in GB and must contain only digits"
# Order packages alphabetically, separate each package with ", "
PACKAGES=$(echo $PACKAGES | sed "s/[, ]\+/\n/g" | LC_ALL=C sort -u \
| awk 'ORS=", "' | sed "s/[, ]*$//")
# Attempt to detect well-known http caching proxies on localhost,
# cf. bash(1) section "REDIRECTION". This is not bullet-proof.
if ! [ -v http_proxy ]; then
while read port proxy; do
(</dev/tcp/localhost/$port) 2>/dev/null || continue
DETECTED_CACHING_PROXY="$port $proxy"
export http_proxy="http://10.0.2.2:$port"
break
done <<< "$WELL_KNOWN_CACHING_PROXIES"
fi
# Print a summary
{
echo "# Proxy configuration:"
if [ "$DETECTED_CACHING_PROXY" ]; then
read port proxy <<< $DETECTED_CACHING_PROXY
echo "Detected caching proxy $(b $proxy) on port $(b $port)."
fi
if [ "${http_proxy:-}" ]; then
echo "Using proxy via environment variable: $(b http_proxy=$http_proxy)."
else
echo "No http proxy configured, all packages will be downloaded from Internet."
fi
[ "$MIRROR" ] && echo "* mirror: $(b $MIRROR)"
[ "$BRANCH" ] && echo "* branch: $(b $BRANCH)"
[ "$DESKTOP" ] && echo "* desktop environment: $(b $DESKTOP)"
[ "$TOOLSET" ] && echo "* tool selection: $(b $TOOLSET)"
[ "$PACKAGES" ] && echo "* additional packages: $(b $PACKAGES)"
[ "$USERNAME" ] && echo "* username & password: $(b $USERNAME $PASSWORD)"
[ "$LOCALE" ] && echo "* locale: $(b $LOCALE)"
[ "$TIMEZONE" ] && echo "* timezone: $(b $TIMEZONE)"
} | kali_message "TL OSINT VM Build"
# Notes regarding the scratch size needed to build a Kali image from scratch
# (ie. in one step, no intermediary rootfs), using the kali-rolling branch and
# xfce desktop, and changing only the toolset. Default toolset needs 14G,
# large toolset 24G and everything toolset 40G. That was back in June 2022.
# Now set default debos options, unless user passed it explicitly after '--'.
echo "$@" | grep -q -e "-m[= ]" -e "--memory[= ]" \
|| set -- "$@" --memory=4G
echo "$@" | grep -q -e "--scratchsize[= ]" \
|| set -- "$@" --scratchsize=45G
mkdir -p $OUTDIR
echo "Building image from recipe $(b tlosint.yaml) ..."
OUTPUT=$OUTDIR/tl-osint-$VERSION-$VARIANT-$ARCH
debos "$@" \
-t arch:$ARCH \
-t branch:$BRANCH \
-t desktop:$DESKTOP \
-t format:$FORMAT \
-t imagename:$OUTPUT \
-t keep:$KEEP \
-t locale:$LOCALE \
-t mirror:$MIRROR \
-t packages:"$PACKAGES" \
-t password:"$PASSWORD" \
-t size:$SIZE \
-t timezone:$TIMEZONE \
-t toolset:$TOOLSET \
-t username:$USERNAME \
-t variant:$VARIANT \
-t zip:$ZIP \
tlosint.yaml
cat << EOF
Finished
EOF