-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild
executable file
·334 lines (284 loc) · 8.66 KB
/
build
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
#!/bin/bash
[[ "$EUID" != "0" ]] && echo "You must run this as root" && exit 1
# PATHS
ROOT="$(realpath `dirname $0`)" # this repo
CONF_D="/usr/local/etc/aegis"
ARTIFACTS="${ROOT}/artifacts"
FW_RULES="/rw/config/qubes-firewall.d"
SYSTEMD_DIR="/usr/lib/systemd/system"
FEDORA_FLAG="/etc/fedora-release" # if this file exists; it's fedora
SCRIPTS="/usr/local/bin"
USER_FILE="${CONF_D}/user" # no need for this if using QubesDB
UNPRIV_USER="user" # TODO: use QubesDB /default-user
# NAMES
APP="aegis"
UNIT="${APP}" # unit file name without .service
SCRIPT="${APP}" # script name for both dom0 and domu
DOM0_SCRIPT="dom0--${APP}" # artifacts/dom0--aegis
DOMU_SCRIPT="domu--${APP}" # artifacts/domu--aegis
PROFILE_D="${APP}.sh"
SERVICE="${UNIT}.service" # full service name
FW_SCRIPT="fw.sh" # becomes /rw/config/qubes-firewall.d/50_aegis
FW_RULE_NAME="50_${APP}" # name of rule in /rw/config/qubes-firewall.d/
TUN_NAME="tun" # DispVM
TUN_T_NAME="tun-t" # DispVM template (if used)
FEAT_SEARCH_PAT="vm-config.aegis--conf-pattern" # the pattn of confs to use for --random
PROFILE_D_PATH="/etc/profile.d/$PROFILE_D" # for convenience
trap 'echo "An error occured" >&2' ERR
function _link_fw_script() {
mkdir -vp "$FW_RULES"
ln -vfs "${ARTIFACTS}/${FW_SCRIPT}" "${FW_RULES}/${FW_RULE_NAME}"
}
function _delete_fw_script() {
rm -vf "${FW_RULES}/${FW_RULE_NAME}"
}
function _help() {
cat << EOF
Usage: `basename $0` [COMMAND]
COMMAND
i,install for TemplateVMs, install system dependencies
for AppVms, install scripts and rules
u,uninstall for TemplateVMs, ask to uninstall system dependencies
for AppVms, uninstall scripts and rules
EOF
}
# echo an OS identifier; update this when adding support for new templates
function get_os() {
if [[ -f "$FEDORA_FLAG" ]]; then
echo "fedora"
fi
}
function this_is() {
case "$1" in
tunvm) [[ "`qubesdb-read /vm-config/aegis--vmtype`" == "tunvm" ]] && return 0 || return 1;;
proxyvm|templatevm) [[ -e "/run/qubes/this-is-$1" ]] && return 0 || return 1;;
dom0) [[ `hostname` == "dom0" ]] && return 0 || return 1;;
esac
}
function _install_deps() {
local os="`get_os`"
case "$os" in
fedora) dnf install -y wireguard-tools;;
*) echo "Unknown OS: '$os'"; exit 1;;
esac
}
function _uninstall_deps() {
local os="`get_os`"
case "$os" in
fedora) dnf remove wireguard-tools;;
*) echo "Unknown OS: '$os'"; exit 1;;
esac
}
function _create_conf_dirs() {
mkdir -vp "${CONF_D}/confs/wg/proton/secure-core"
}
function _delete_config_dir() {
rm -rf "${CONF_D}"
}
function _install_service() {
local src="${ARTIFACTS}/${SERVICE}"
local dst="${SYSTEMD_DIR}/${SERVICE}"
sed -e "s|<<APP_NAME>>|${APP^}|g" \
-e "s|<<SCRIPT_PATH>>|${SCRIPTS}/${SCRIPT}|g" \
"$src" > "$dst"
chown -v root:root "$dst"
systemctl daemon-reload
systemctl enable "$SERVICE"
# create qvm-service unit file
local service_d="/etc/systemd/system/${SERVICE}.d"
mkdir -vp "$service_d"
# qvm-service --enable aegis will touch a file called "$UNIT" (e.g. aegis; without .service)
echo -e "[Unit]\nConditionPathExists=/var/run/qubes-service/${UNIT}" \
> "${service_d}/30_${UNIT}.conf"
}
function _uninstall_service() {
systemctl stop "$SERVICE"
systemctl disable "$SERVICE" || exit 1
rm -vf "${SYSTEMD_DIR}/${SERVICE}"
systemctl daemon-reload
# create qvm-service unit file
local service_d="/etc/systemd/system/${SERVICE}.d"
rm -rfv "$service_d"
}
function _install_domu_script() {
local src="${ARTIFACTS}/${DOMU_SCRIPT}"
local dst="${SCRIPTS}/${SCRIPT}"
mkdir -vp "$SCRIPTS"
cp -v "$src" "$dst"
chmod +x "$dst"
chown root:root "$dst"
}
function _uninstall_domu_script() {
rm -vf "${SCRIPTS}/${SCRIPT}"
}
function _set_conf_perms() {
find "${CONF_D}" -type d -exec chmod -v 700 {} \;
find "${CONF_D}" -type f -exec chmod -v 600 {} \;
chmod -v 700 "${CONF_D}"
}
function _confirm() {
printf "$1 [y/N]: "
read -r answer
[[ "${answer^^}" == "Y" ]] && return 0 || return 1
}
function _determine_unpriv_user() {
if id -u user &>/dev/null; then
echo "user" > "${USER_FILE}"
else
user=`awk -F: '$3 >= 1000 {if (!min || $3 < min) {min = $3; name = $1}} END {print name}' /etc/passwd`
while true; do
printf "Input an unprivileged account with X access [${user}]: "
read -r answer
if [[ -z "$answer" ]]; then
local choice="$user"
else
local choice="$answer"
fi
if _confirm "Confirm '${choice}'?"; then
break
fi
done
echo "$choice" > "${USER_FILE}"
fi
}
function _read_tun_name() {
grep "TUN_NAME" "$PROFILE_D_PATH" | cut -d'=' -f2 | tr -d '"' | tr -d "[:space:]"
}
function _create_profile_d() {
# it already exists, verify or modify it
if [[ -f "$PROFILE_D_PATH" ]]; then
while true; do
echo ""
cat "$PROFILE_D_PATH"
echo ""
if _confirm "Is this config correct?"; then
TUN_NAME="`_read_tun_name`"
return 0
fi
sudo "${EDITOR:-vi}" "$PROFILE_D_PATH"
done
fi
# it doesn't exist, let's go through it
while true; do
printf "Specify qube name [tun]: "
read -r answer
local tun_name="${answer:-tun}"
tun_name=$(echo "$tun_name" | tr -d '"' | tr -d "[:space:]")
if _confirm "Confirm '${tun_name}'?"; then
break
fi
done
TUN_NAME="$tun_name"
TUN_T_NAME="${tun_name}-t"
local f="$PROFILE_D_PATH"
echo "TUN_NAME=\"${TUN_NAME}\"" > "$f" && echo "$f created"
chmod -v 644 "$f"
chown -v root:root "$f"
}
function _remove_profile_d() {
rm -vf "$PROFILE_D_PATH"
}
function _create_qubes() {
if ! _confirm "Create qubes?"; then
return 0
fi
if _confirm "Use DispVM setup?"; then
while true; do
# TUN_NAME is /always/ set in _create_profile_d(); it will use the users
# chosen value, if it's already set in the profile.d file.
local default_tun_name="${TUN_NAME:-tun}-t"
printf "Specify DispVM template name [${default_tun_name}]: "
read -r answer
local choice="${answer:-$default_tun_name}"
choice=$(echo "$choice" | tr -d '"' | tr -d "[:space:]")
if _confirm "Confirm '${choice}'?"; then
TUN_T_NAME="$choice"
break
fi
done
set -e
qvm-create "${TUN_T_NAME}" \
--label black \
--property template_for_dispvms=True
qvm-prefs --set "${TUN_T_NAME}" default_dispvm "$TUN_T_NAME"
qvm-features "$TUN_T_NAME" vm-config.aegis--vmtype 'tunvm' || exit 1
qvm-create "$TUN_NAME" \
--label purple \
--class DispVM \
--property template="${TUN_T_NAME}" \
--property default_dispvm="${TUN_T_NAME}" \
--property provides_network=True
set +e
else
qvm-create "$TUN_NAME" \
--label purple \
--property provides_network=True \
|| exit 1
fi
qvm-service -e "$TUN_NAME" aegis || exit 1
qvm-features "$TUN_NAME" vm-config.aegis--vmtype 'tunvm' || exit 1
}
function _install_dom0_script() {
local trg="${SCRIPTS}/${SCRIPT}"
mkdir -vp "$SCRIPTS"
sed -e "s|<<REMOTE_SCRIPT>>|${SCRIPTS}/${SCRIPT}|g" \
-e "s|<<PROFILE_D_PATH>>|${PROFILE_D_PATH}|g" \
-e "s|<<FEAT_SEARCH_PAT>>|${FEAT_SEARCH_PAT}|g" \
"${ARTIFACTS}/${DOM0_SCRIPT}" > "$trg" || exit 1
chmod -v 755 "$trg"
chown -v root:root "$trg"
}
function _uninstall_dom0_script() {
rm -f "${SCRIPTS}/${SCRIPT}"
}
case "$1" in
i|install)
if this_is "tunvm"; then
echo installing for AppVM..
_create_conf_dirs # creates /usr/local/etc/aegis, so do this first
_determine_unpriv_user
_link_fw_script
_install_domu_script
_set_conf_perms
elif this_is "templatevm"; then
echo installing for TemplateVM..
_install_deps
_install_service
elif this_is "dom0"; then
echo installing for Dom0..
_create_profile_d
_create_qubes
_install_dom0_script
else
echo unknown VM type, cannot install..
fi
;;
u|uninstall)
if this_is "tunvm"; then
echo uninstalling for AppVM..
_delete_fw_script
_uninstall_domu_script
if _confirm "[WARNING] Delete config dir, and all of your tunnel confs?"; then
echo deleting all confs..
_delete_config_dir
else
echo confs preserved
fi
elif this_is "templatevm"; then
echo uninstalling for TemplateVM..
_uninstall_deps
_uninstall_service
elif this_is "dom0"; then
echo uninstalling for Dom0..
_remove_profile_d
_uninstall_dom0_script
echo "Remove the tun qubes yourself"
else
echo unknown VM type, cannot uninstall..
fi
;;
h|help|-h|--help)
_help
;;
*) echo "Unknown option: '$1'"; _help;;
esac