forked from opengrep/opengrep
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·343 lines (302 loc) · 11 KB
/
install.sh
File metadata and controls
executable file
·343 lines (302 loc) · 11 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
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
#!/usr/bin/env bash
# Opengrep installation script
set -euo pipefail
if [[ "$0" == "bash" || "$0" == "-bash" ]]; then
SCRIPT_NAME="install.sh (via stdin)"
else
SCRIPT_NAME="$0"
fi
print_usage() {
echo "Usage:"
echo " $SCRIPT_NAME [-v <version>] [--verify-signatures]"
echo " Install the latest or specified version (default: latest)"
echo
echo " $SCRIPT_NAME -l"
echo " List the latest 3 available versions"
echo
echo " $SCRIPT_NAME -h"
echo " Show this help message"
echo
echo "Options:"
printf " %-22s %s\n" "-v <version>" "Specify version to install (optional)"
printf " %-22s %s\n" "--verify-signatures" "Require Cosign verification of signature"
printf " %-22s %s\n" "-l" "List latest 3 versions (no install)"
printf " %-22s %s\n" "-h" "Display help (no install)"
echo
echo "Notes:"
echo " - '--verify-signatures' can be used with or without '-v'."
echo " - '-l' and '-h' cannot be combined with other options."
}
check_has_curl() {
command -v curl > /dev/null 2>&1 || {
echo >&2 "Required tool curl could not be found. Aborting."
exit 1
}
}
# Function to get available versions - already checked when running main
get_available_versions() {
check_has_curl
curl -s https://api.github.com/repos/opengrep/opengrep/releases |
grep '"tag_name":' |
sed -E 's/.*"([^"]+)".*/\1/'
}
# Function to validate version
validate_version() {
local VERSION="$1"
local AVAILABLE_VERSIONS
AVAILABLE_VERSIONS=$(get_available_versions)
if echo "$AVAILABLE_VERSIONS" | grep -q "^$VERSION$"; then
return 0
else
echo "Error: Version $VERSION not found"
echo "Available versions (latest 3):"
echo "$AVAILABLE_VERSIONS" | head -3
exit 1
fi
}
# pre: $SIG_EXISTS == "true"
validate_signature() {
local P="$1"
if $HAS_COSIGN; then
echo "Verifying signatures for ${P}/opengrep.cert"
if cosign verify-blob \
--cert "$P/opengrep.cert" \
--signature "${P}/opengrep.sig" \
--certificate-identity-regexp "https://github.com/opengrep/opengrep.+" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
"${P}/opengrep"; then
echo "Signature valid."
else
# if we have signatures and we also have cosign installed, then always
# verify, even without --verify-signatures.
echo "Error: Signature validation error."
exit 1
fi
else
echo "Warning: cosign needed for signature validation; the package will still be installed."
echo "If this was not intended, delete and rerun with --verify-signatures or install cosign."
fi
}
# carefully cleanup the expected files; we don't want a programming error to run
# rm -rf on any directory that is not intended...
cleanup_on_failure() {
local P="$1"
echo "An error occurred during the installation. Cleaning up ${P}..."
rm -f "${P}/opengrep" || true
rm -f "${P}/opengrep.sig" || true
rm -f "${P}/opengrep.cert" || true
rmdir "${P}" || true
exit 1
}
main() {
local VERSION="$1"
local VERIFY_SIGNATURES="$2"
PREFIX="${HOME}/.opengrep/cli"
INST="${PREFIX}/${VERSION}"
LATEST="${PREFIX}/latest"
OS="${OS:-$(uname -s)}"
ARCH="${ARCH:-$(uname -m)}"
DIST=""
check_has_curl
# check and set "os_arch"
if [ "$OS" = "Linux" ]; then
if ldd /bin/sh 2>&1 | grep -qi musl; then
if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then
DIST="opengrep_musllinux_x86"
elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
DIST="opengrep_musllinux_aarch64"
fi
else
if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then
DIST="opengrep_manylinux_x86"
elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
DIST="opengrep_manylinux_aarch64"
fi
fi
elif [ "$OS" = "Darwin" ]; then
if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then
DIST="opengrep_osx_x86"
elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
DIST="opengrep_osx_arm64"
fi
fi
if [ -z "${DIST}" ]; then
echo "Operating system '${OS}' / architecture '${ARCH}' is unsupported." 1>&2
exit 1
fi
URL="https://github.com/opengrep/opengrep/releases/download/${VERSION}/${DIST}"
# check if binary already exists
if [ -f "${INST}/opengrep" ]; then
echo "Destination binary ${INST}/opengrep already exists."
rm -f "${LATEST}" || exit 1
ln -s "${INST}" "${LATEST}" || exit 1
echo "Updated symlink from ${LATEST}/opengrep to point to ${INST}/opengrep."
if $VERIFY_SIGNATURES; then
echo "Signature verification skipped for existing installation."
fi
else
echo
echo "*** Installing Opengrep ${VERSION} for ${OS} (${ARCH}) ***"
# cleanup on error
trap '[ "$?" -eq 0 ] || cleanup_on_failure $INST' EXIT
mkdir -p "${INST}"
if [ ! -d "${INST}" ]; then
echo "Failed to create install directory ${INST}." 1>&2
exit 1
fi
curl --fail --location --progress-bar "${URL}" > "${INST}/opengrep"
local SIG_EXISTS=true
# Try downloading .cert
CERT_STATUS=$(curl --location --silent --show-error --write-out "%{http_code}" \
--output "${INST}/opengrep.cert" "${URL}.cert")
if [[ "$CERT_STATUS" == "404" ]]; then
SIG_EXISTS=false
rm -f "${INST}/opengrep.cert" # It's there but contains "Not found".
echo "Warning: Certificate file not found at ${URL}.cert"
elif [[ "$CERT_STATUS" != 200 ]]; then
echo "Error: Failed to download ${URL}.cert: HTTP status $CERT_STATUS."
exit 1
else
# Only attempt .sig if .cert was found
SIG_STATUS=$(curl --location --silent --show-error --write-out "%{http_code}" \
--output "${INST}/opengrep.sig" "${URL}.sig")
if [[ "$SIG_STATUS" == "404" ]]; then
SIG_EXISTS=false
echo "Error: Signature file not found at ${URL}.sig, but ${URL}.cert was found."
exit 1 # we downloaded .cert, so exit with error
elif [[ "$SIG_STATUS" != 200 ]]; then
echo "Error: Failed to download ${URL}.sig: HTTP status $SIG_STATUS."
exit 1
fi
fi
# check signature if SIG_EXIST
if [[ "$SIG_EXISTS" == true ]]; then
validate_signature "${INST}"
else
if [[ "$VERIFY_SIGNATURES" == true ]]; then
echo "Error: No signature / certificate found for ${VERSION} but --verify-signatures was requested."
echo "Error: It is likely that signature verification was added after this version."
exit 1
else
echo "Warning: No signature / certificate found for ${VERSION}. Skipping signature verification."
echo "Warning: The package will still be installed. It is likely that signature verification was added after this version."
fi
fi
# make executable by all users
chmod a+x "${INST}/opengrep" || exit 1
if [ ! -f "${INST}/opengrep" ]; then
echo "Failed to download binary at ${INST}/opengrep" 1>&2
exit 1
fi
echo "Testing binary..."
# Test by calling --version on the downloaded binary
TEST=$("${INST}/opengrep" --version 2> /dev/null || true)
if [ -z "$TEST" ]; then
echo "Failed to execute installed binary: ${INST}/opengrep." 1>&2
exit 1
fi
echo
echo "Successfully installed Opengrep binary at ${INST}/opengrep"
rm -f "${LATEST}" || exit 1
ln -s "${INST}" "${LATEST}" || exit 1
echo "with a symlink from ${LATEST}/opengrep"
fi
LOCALBIN="${HOME}/.local/bin"
# Only need to create the symlink from .local/bin once if not created before.
# For all subsequent installations, the ./local/bin symlink will still point
# to the updated symlink (created above).
if [ -d "${LOCALBIN}" ] && [ -w "${LOCALBIN}" ]; then
# Only create the symlink if it doesn't already exist
if [ ! -f "${LOCALBIN}/opengrep" ]; then
ln -s "${LATEST}/opengrep" "${LOCALBIN}/opengrep"
echo "Created symlink from ${LOCALBIN}/opengrep to ${LATEST}/opengrep"
fi
echo
echo "To launch Opengrep now, type:"
# Do not assume that ~/.local/bin is in the PATH even if it exists,
# as it is not always the case.
if echo "$PATH" | tr ':' '\n' | grep -Fxq "$HOME/.local/bin"; then
echo "opengrep"
else
echo "${LOCALBIN}/opengrep"
fi
echo
else
echo
echo "To launch Opengrep now, type:"
echo "${LATEST}/opengrep"
echo
echo "Hint: Append the following line to your shell profile:"
echo "export PATH='${LATEST}':\$PATH"
echo
fi
}
# Argument parsing
if command -v cosign &> /dev/null; then
HAS_COSIGN=true
else
HAS_COSIGN=false
fi
HELP=false
LIST=false
VERIFY_SIGNATURES=false
VERSION=""
while [[ $# -gt 0 ]]; do
case "$1" in
-h)
HELP=true
shift
;;
-l)
LIST=true
shift
;;
--verify-signatures)
VERIFY_SIGNATURES=true
shift
;;
-v)
if [[ -z "${2-}" ]] || ! [[ -n "$2" && "$2" != -* ]]; then
echo "Error: -v requires a version argument."
exit 1
else
VERSION="$2"
shift 2
fi
;;
*)
echo "Error: Unknown option: $1."
print_usage
exit 1
;;
esac
done
if { { $VERIFY_SIGNATURES || [[ -n "$VERSION" ]] || $LIST; } && $HELP; } || { { $VERIFY_SIGNATURES || [[ -n "$VERSION" ]] || $HELP; } && $LIST; }; then
echo "Error: incorrect arguments:"
print_usage
exit 1
fi
if $VERIFY_SIGNATURES && ! $HAS_COSIGN; then
echo "Error: cosign is required for --verify-signatures but is not installed."
echo "Go to https://github.com/sigstore/cosign to install it or run without the --verify-signatures flag to install without signature verification."
exit 1
elif ! $HAS_COSIGN; then
echo "Warning: cosign is required for --verify-signatures but is not installed. Skipping signature validation."
echo "Go to https:/github.com/sigstore/cosign to install it."
fi
if "$HELP"; then
print_usage
exit 0
fi
if $LIST; then
echo "Available versions (latest 3):"
get_available_versions | head -3
exit 0
fi
shift $((OPTIND - 1))
if [ -z "$VERSION" ]; then
VERSION=$(get_available_versions | head -1)
else
validate_version "$VERSION"
fi
main "$VERSION" "$VERIFY_SIGNATURES"