-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvector.sh
More file actions
executable file
·316 lines (272 loc) · 8.19 KB
/
Copy pathvector.sh
File metadata and controls
executable file
·316 lines (272 loc) · 8.19 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
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
#!/usr/bin/env bash
set -euo pipefail
IMAGE_NAME="${VECTOR_IMAGE:-vector}"
CLI_CONTAINER_NAME="${VECTOR_CLI_CONTAINER_NAME:-vector-cli}"
GUI_CONTAINER_NAME="${VECTOR_GUI_CONTAINER_NAME:-vector-gui}"
GUI_PORT_DEFAULT="${VECTOR_PORT:-5992}"
SRC_MOUNT_POINT="/src"
OUTPUT_MOUNT_POINT="/output"
CBOM_MOUNT_POINT="/cbom-input"
GUI_HOST_MOUNT_POINT="/mnt/host-home"
SCRIPT_NAME="$(basename "$0")"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
info() { printf '%s: %s\n' "$SCRIPT_NAME" "$1"; }
err() { printf '%s: error: %s\n' "$SCRIPT_NAME" "$1" >&2; }
validate_identifier() {
local value="$1" label="$2"
if [[ ! "$value" =~ ^[a-zA-Z0-9][a-zA-Z0-9_.-]*$ ]]; then
err "${label} ('${value}') is not a valid Docker name: it must start with a letter or digit and contain only letters, digits, '_', '.', or '-' — no spaces."
return 1
fi
return 0
}
validate_identifier "$IMAGE_NAME" "VECTOR_IMAGE" || exit 1
validate_identifier "$CLI_CONTAINER_NAME" "VECTOR_CLI_CONTAINER_NAME" || exit 1
validate_identifier "$GUI_CONTAINER_NAME" "VECTOR_GUI_CONTAINER_NAME" || exit 1
usage() {
cat <<EOF
Usage:
./${SCRIPT_NAME}
Start VECTOR-GUI (same as "gui" below). Builds the image first only
if it doesn't exist yet.
./${SCRIPT_NAME} gui [--port PORT] [--source-dir DIR]
Start VECTOR-GUI and print the local address to open in a browser.
--port local port to publish (default: ${GUI_PORT_DEFAULT})
--source-dir host directory to make available inside the
container at ${GUI_HOST_MOUNT_POINT}, so it can be
entered as a source path in the web form
(default: the directory containing this script)
./${SCRIPT_NAME} cli
Show the vector CLI help.
./${SCRIPT_NAME} cli <command> [args...]
Run "vector <command> [args...]" inside the container.
<command> is one of: code, network, score.
./${SCRIPT_NAME} build
Build (or rebuild) the image unconditionally — run this after
changing code.
./${SCRIPT_NAME} help | -h | --help
Show help message.
Examples:
./${SCRIPT_NAME}
./${SCRIPT_NAME} gui --port 8080 --source-dir ~/projects
./${SCRIPT_NAME} cli code /path/to/project --name my-app --output ./results
./${SCRIPT_NAME} cli network --protocol tls --target example.com --port 443 --output ./results
./${SCRIPT_NAME} cli score ./results/cbom/crypto-combined-cbom.json
./${SCRIPT_NAME} build
EOF
}
require_docker() {
if ! command -v docker >/dev/null 2>&1; then
err "Docker was not found on PATH. Install Docker Engine and try again."
exit 1
fi
}
do_build() {
info "Building ${IMAGE_NAME} from Dockerfile..."
if ! docker build -t "$IMAGE_NAME" -f "$SCRIPT_DIR/Dockerfile" "$SCRIPT_DIR"; then
err "Image build failed; not starting a container."
exit 1
fi
}
ensure_image() {
require_docker
if docker image inspect "$IMAGE_NAME" >/dev/null 2>&1; then
return 0
fi
info "Image '${IMAGE_NAME}' not found locally."
do_build
}
cmd_build() {
require_docker
do_build
}
tty_flags() {
if [ -t 0 ] && [ -t 1 ]; then
printf '%s\n' "-it"
else
printf '%s\n' "-i"
fi
}
abspath() {
if [ -d "$1" ]; then
(cd "$1" && pwd)
else
(cd "$(dirname "$1")" && printf '%s/%s' "$(pwd)" "$(basename "$1")")
fi
}
validate_dir() {
local path="$1" label="$2"
if [ ! -e "$path" ]; then
err "${label} directory does not exist: ${path}"
err "Create it first, e.g.: mkdir -p \"${path}\""
return 1
fi
if [ ! -d "$path" ]; then
err "${label} path exists but is not a directory: ${path}"
return 1
fi
return 0
}
validate_file() {
local path="$1" label="$2"
if [ ! -e "$path" ]; then
err "${label} file does not exist: ${path}"
return 1
fi
if [ ! -f "$path" ]; then
err "${label} path exists but is not a regular file: ${path}"
return 1
fi
return 0
}
is_github_url() {
[[ "$1" =~ ^https://github\.com/ ]] || [[ "$1" =~ ^git@github\.com: ]]
}
cmd_gui() {
local port="$GUI_PORT_DEFAULT"
local source_dir="$SCRIPT_DIR"
while [ "$#" -gt 0 ]; do
case "$1" in
--port)
shift
[ "$#" -gt 0 ] || { err "--port requires a value."; return 1; }
port="$1"; shift ;;
--source-dir)
shift
[ "$#" -gt 0 ] || { err "--source-dir requires a value."; return 1; }
source_dir="$1"; shift ;;
-h|--help)
usage; return 0 ;;
*)
err "Unrecognized gui option: $1"
usage
return 1 ;;
esac
done
local -a mounts=()
if [ -n "$source_dir" ]; then
validate_dir "$source_dir" "Source" || return 1
mounts+=(-v "$(abspath "$source_dir"):${GUI_HOST_MOUNT_POINT}")
info "Host directory available inside the container at ${GUI_HOST_MOUNT_POINT}"
fi
info "Starting VECTOR-GUI — open http://localhost:${port} once it reports running (Ctrl+C to stop)"
docker run --rm $(tty_flags) --name "$GUI_CONTAINER_NAME" \
-p "${port}:${port}" \
-e "VECTOR_PORT=${port}" \
"${mounts[@]}" \
"$IMAGE_NAME" gui --port "${port}"
}
cmd_cli() {
if [ "$#" -eq 0 ]; then
docker run --rm $(tty_flags) --name "$CLI_CONTAINER_NAME" "$IMAGE_NAME"
return $?
fi
local subcommand="$1"; shift
local -a passthrough=("$subcommand")
local -a mounts=()
local wrote_output_note=0
local help_requested=0
local a
for a in "$@"; do
if [ "$a" = "-h" ] || [ "$a" = "--help" ]; then
help_requested=1
break
fi
done
if [ "$subcommand" = "-h" ] || [ "$subcommand" = "--help" ] || [ "$subcommand" = "help" ]; then
help_requested=1
fi
case "$subcommand" in
code)
if [ "$#" -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
passthrough+=("$@")
else
local src="$1"; shift
if is_github_url "$src"; then
passthrough+=("$src")
else
validate_dir "$src" "Source" || return 1
mounts+=(-v "$(abspath "$src"):${SRC_MOUNT_POINT}")
passthrough+=("${SRC_MOUNT_POINT}")
fi
while [ "$#" -gt 0 ]; do
case "$1" in
--output)
shift
[ "$#" -gt 0 ] || { err "--output requires a value."; return 1; }
validate_dir "$1" "Output" || return 1
mounts+=(-v "$(abspath "$1"):${OUTPUT_MOUNT_POINT}")
passthrough+=(--output "${OUTPUT_MOUNT_POINT}")
wrote_output_note=1
shift ;;
*) passthrough+=("$1"); shift ;;
esac
done
fi
;;
network)
while [ "$#" -gt 0 ]; do
case "$1" in
--output)
shift
[ "$#" -gt 0 ] || { err "--output requires a value."; return 1; }
validate_dir "$1" "Output" || return 1
mounts+=(-v "$(abspath "$1"):${OUTPUT_MOUNT_POINT}")
passthrough+=(--output "${OUTPUT_MOUNT_POINT}")
wrote_output_note=1
shift ;;
*) passthrough+=("$1"); shift ;;
esac
done
;;
score)
if [ "$#" -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
passthrough+=("$@")
else
local cbom="$1"; shift
validate_file "$cbom" "CBOM" || return 1
mounts+=(-v "$(dirname "$(abspath "$cbom")"):${CBOM_MOUNT_POINT}")
passthrough+=("${CBOM_MOUNT_POINT}/$(basename "$cbom")")
passthrough+=("$@")
fi
;;
-h|--help|help)
:
;;
*)
passthrough+=("$@")
;;
esac
if [ "$wrote_output_note" -eq 0 ] && [ "$help_requested" -eq 0 ] && { [ "$subcommand" = "code" ] || [ "$subcommand" = "network" ]; }; then
info "No --output given: results stay inside this container and are lost on exit. Add --output <dir> to persist them on the host."
fi
docker run --rm $(tty_flags) --name "$CLI_CONTAINER_NAME" \
--user "$(id -u):$(id -g)" \
"${mounts[@]}" \
"$IMAGE_NAME" "${passthrough[@]}"
}
main() {
if [ "$#" -eq 0 ]; then
ensure_image
cmd_gui
return $?
fi
local action="$1"; shift
case "$action" in
build)
cmd_build "$@" ;;
gui)
ensure_image
cmd_gui "$@" ;;
cli)
ensure_image
cmd_cli "$@" ;;
help|-h|--help)
usage ;;
*)
err "Unrecognized command: ${action}"
usage
exit 1 ;;
esac
}
main "$@"