changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > infra / bootstrap.sh

changeset 251: 80e639d0b203
parent: 5d84c4505479
child: e2b8d0be0d24
author: Richard Westhaver <ellis@rwest.io>
date: Wed, 05 Jun 2024 23:34:14 +0000
permissions: -rwxr-xr-x
description: quick fixes
1 #!/bin/sh
2 set -eu
3 main() {
4  . ./check.sh
5  download --check
6  local _arch=$(_read arch | tr -d '"')
7  local _ext=""
8  case "$_arch" in
9  *windows*)
10  _ext=".exe"
11  ;;
12  esac
13  local _url="https://packy.compiler.company/dist/${_arch}"
14  local _stash
15  if ! _stash=".stash"; then
16  # Because the previous command ran in a subshell, we must manually
17  # propagate exit status.
18  exit 1
19  fi
20  ensure mkdir -p "${_stash}/src"
21  ensure mkdir -p "${_stash}/bin"
22  local _sk_url="${_url}/bin/sk"
23  local _sbcl_url="${_url}/pack/sbcl.tar.zst"
24  local _rocksdb_url="${_url}/pack/rocksdb.tar.zst"
25  ensure download "$_sbcl_url" "${_stash}/src/sbcl.tar.zst" "$_arch"
26  ensure download "$_rocksdb_url" "${_stash}/src/rocksdb.tar.zst" "$_arch"
27  ensure download "$_sk_url" "${_stash}/bin/sk" "$_arch"
28  chmod +x "${_stash}/bin/sk"
29  say "OK ${_stash}/bin/sk"
30 }
31 
32 _read() {
33  grep ":$1" $INFRA_HOST_CONFIG | cut -d' ' -f 2-
34 }
35 
36 say() {
37  printf 'bootstrap.sh: %s\n' "$1"
38 }
39 
40 err() {
41  say "$1" >&2
42  exit 1
43 }
44 
45 check_cmd() {
46  command -v "$1" > /dev/null 2>&1
47 }
48 
49 need_cmd() {
50  if ! check_cmd "$1"; then
51  err "need '$1' (command not found)"
52  fi
53 }
54 
55 # Run a command that should never fail. If the command fails execution
56 # will immediately terminate with an error showing the failing
57 # command.
58 ensure() {
59  if ! "$@"; then err "command failed: $*"; fi
60 }
61 
62 # Check if curl supports the --retry flag, then pass it to the curl invocation.
63 check_curl_for_retry_support() {
64  local _retry_supported=""
65  # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
66  if check_help_for "notspecified" "curl" "--retry"; then
67  _retry_supported="--retry 3"
68  if check_help_for "notspecified" "curl" "--continue-at"; then
69  # "-C -" tells curl to automatically find where to resume the download when retrying.
70  _retry_supported="--retry 3 -C -"
71  fi
72  fi
73 
74  RETVAL="$_retry_supported"
75 }
76 
77 # Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
78 # if support by local tools is detected. Detection currently supports these curl backends:
79 # GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
80 get_ciphersuites_for_curl() {
81  if [ -n "${TLS_CIPHERSUITES-}" ]; then
82  # user specified custom cipher suites, assume they know what they're doing
83  RETVAL="$TLS_CIPHERSUITES"
84  return
85  fi
86 
87  local _openssl_syntax="no"
88  local _gnutls_syntax="no"
89  local _backend_supported="yes"
90  if curl -V | grep -q ' OpenSSL/'; then
91  _openssl_syntax="yes"
92  elif curl -V | grep -iq ' LibreSSL/'; then
93  _openssl_syntax="yes"
94  elif curl -V | grep -iq ' BoringSSL/'; then
95  _openssl_syntax="yes"
96  elif curl -V | grep -iq ' GnuTLS/'; then
97  _gnutls_syntax="yes"
98  else
99  _backend_supported="no"
100  fi
101 
102  local _args_supported="no"
103  if [ "$_backend_supported" = "yes" ]; then
104  # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
105  if check_help_for "notspecified" "curl" "--tlsv1.2" "--ciphers" "--proto"; then
106  _args_supported="yes"
107  fi
108  fi
109 
110  local _cs=""
111  if [ "$_args_supported" = "yes" ]; then
112  if [ "$_openssl_syntax" = "yes" ]; then
113  _cs=$(get_strong_ciphersuites_for "openssl")
114  elif [ "$_gnutls_syntax" = "yes" ]; then
115  _cs=$(get_strong_ciphersuites_for "gnutls")
116  fi
117  fi
118 
119  RETVAL="$_cs"
120 }
121 
122 # Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
123 # if support by local tools is detected. Detection currently supports these wget backends:
124 # GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
125 get_ciphersuites_for_wget() {
126  if [ -n "${TLS_CIPHERSUITES-}" ]; then
127  # user specified custom cipher suites, assume they know what they're doing
128  RETVAL="$TLS_CIPHERSUITES"
129  return
130  fi
131 
132  local _cs=""
133  if wget -V | grep -q '\-DHAVE_LIBSSL'; then
134  # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
135  if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
136  _cs=$(get_strong_ciphersuites_for "openssl")
137  fi
138  elif wget -V | grep -q '\-DHAVE_LIBGNUTLS'; then
139  # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
140  if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
141  _cs=$(get_strong_ciphersuites_for "gnutls")
142  fi
143  fi
144 
145  RETVAL="$_cs"
146 }
147 
148 check_help_for() {
149  local _arch
150  local _cmd
151  local _arg
152  _arch="$1"
153  shift
154  _cmd="$1"
155  shift
156 
157  local _category
158  if "$_cmd" --help | grep -q 'For all options use the manual or "--help all".'; then
159  _category="all"
160  else
161  _category=""
162  fi
163 
164  case "$_arch" in
165 
166  *darwin*)
167  if check_cmd sw_vers; then
168  case $(sw_vers -productVersion) in
169  10.*)
170  # If we're running on macOS, older than 10.13, then we always
171  # fail to find these options to force fallback
172  if [ "$(sw_vers -productVersion | cut -d. -f2)" -lt 13 ]; then
173  # Older than 10.13
174  echo "Warning: Detected macOS platform older than 10.13"
175  return 1
176  fi
177  ;;
178  11.*)
179  # We assume Big Sur will be OK for now
180  ;;
181  *)
182  # Unknown product version, warn and continue
183  echo "Warning: Detected unknown macOS major version: $(sw_vers -productVersion)"
184  echo "Warning TLS capabilities detection may fail"
185  ;;
186  esac
187  fi
188  ;;
189 
190  esac
191 
192  for _arg in "$@"; do
193  if ! "$_cmd" --help "$_category" | grep -q -- "$_arg"; then
194  return 1
195  fi
196  done
197 
198  true # not strictly needed
199 }
200 
201 # Return strong TLS 1.2-1.3 cipher suites in OpenSSL or GnuTLS syntax. TLS 1.2
202 # excludes non-ECDHE and non-AEAD cipher suites. DHE is excluded due to bad
203 # DH params often found on servers (see RFC 7919). Sequence matches or is
204 # similar to Firefox 68 ESR with weak cipher suites disabled via about:config.
205 # $1 must be openssl or gnutls.
206 get_strong_ciphersuites_for() {
207  if [ "$1" = "openssl" ]; then
208  # OpenSSL is forgiving of unknown values, no problems with TLS 1.3 values on versions that don't support it yet.
209  echo "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"
210  elif [ "$1" = "gnutls" ]; then
211  # GnuTLS isn't forgiving of unknown values, so this may require a GnuTLS version that supports TLS 1.3 even if wget doesn't.
212  # Begin with SECURE128 (and higher) then remove/add to build cipher suites. Produces same 9 cipher suites as OpenSSL but in slightly different order.
213  echo "SECURE128:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS-ALL:-CIPHER-ALL:-MAC-ALL:-KX-ALL:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+AES-128-GCM:+CHACHA20-POLY1305:+AES-256-GCM"
214  fi
215 }
216 
217 check_proc() {
218  # Check for /proc by looking for the /proc/self/exe link
219  # This is only run on Linux
220  if ! test -L /proc/self/exe ; then
221  err "fatal: Unable to find /proc/self/exe. Is /proc mounted? Installation cannot proceed without /proc."
222  fi
223 }
224 
225 get_bitness() {
226  need_cmd head
227  # Architecture detection without dependencies beyond coreutils.
228  # ELF files start out "\x7fELF", and the following byte is
229  # 0x01 for 32-bit and
230  # 0x02 for 64-bit.
231  # The printf builtin on some shells like dash only supports octal
232  # escape sequences, so we use those.
233  local _current_exe_head
234  _current_exe_head=$(head -c 5 /proc/self/exe )
235  if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then
236  echo 32
237  elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then
238  echo 64
239  else
240  err "unknown platform bitness"
241  fi
242 }
243 
244 is_host_amd64_elf() {
245  need_cmd head
246  need_cmd tail
247  # ELF e_machine detection without dependencies beyond coreutils.
248  # Two-byte field at offset 0x12 indicates the CPU,
249  # but we're interested in it being 0x3E to indicate amd64, or not that.
250  local _current_exe_machine
251  _current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1)
252  [ "$_current_exe_machine" = "$(printf '\076')" ]
253 }
254 
255 get_endianness() {
256  local cputype=$1
257  local suffix_eb=$2
258  local suffix_el=$3
259 
260  # detect endianness without od/hexdump, like get_bitness() does.
261  need_cmd head
262  need_cmd tail
263 
264  local _current_exe_endianness
265  _current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)"
266  if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then
267  echo "${cputype}${suffix_el}"
268  elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then
269  echo "${cputype}${suffix_eb}"
270  else
271  err "unknown platform endianness"
272  fi
273 }
274 
275 # This wraps curl or wget. Try curl first, if not installed,
276 # use wget instead.
277 download() {
278  local _dld
279  local _ciphersuites
280  local _err
281  local _status
282  local _retry
283  if check_cmd curl; then
284  _dld=curl
285  elif check_cmd wget; then
286  _dld=wget
287  else
288  _dld='curl or wget' # to be used in error message of need_cmd
289  fi
290 
291  if [ "$1" = --check ]; then
292  need_cmd "$_dld"
293  elif [ "$_dld" = curl ]; then
294  check_curl_for_retry_support
295  _retry="$RETVAL"
296  get_ciphersuites_for_curl
297  _ciphersuites="$RETVAL"
298  if [ -n "$_ciphersuites" ]; then
299  _err=$(curl $_retry --proto '=https' --tlsv1.2 --ciphers "$_ciphersuites" --silent --show-error --fail --location "$1" --output "$2" 2>&1)
300  _status=$?
301  else
302  echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
303  if ! check_help_for "$3" curl --proto --tlsv1.2; then
304  echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
305  _err=$(curl $_retry --silent --show-error --fail --location "$1" --output "$2" 2>&1)
306  _status=$?
307  else
308  _err=$(curl $_retry --proto '=https' --tlsv1.2 --silent --show-error --fail --location "$1" --output "$2" 2>&1)
309  _status=$?
310  fi
311  fi
312  if [ -n "$_err" ]; then
313  echo "$_err" >&2
314  if echo "$_err" | grep -q 404$; then
315  err "installer for platform '$3' not found, this may be unsupported"
316  fi
317  fi
318  return $_status
319  elif [ "$_dld" = wget ]; then
320  if [ "$(wget -V 2>&1|head -2|tail -1|cut -f1 -d" ")" = "BusyBox" ]; then
321  echo "Warning: using the BusyBox version of wget. Not enforcing strong cipher suites for TLS or TLS v1.2, this is potentially less secure"
322  _err=$(wget "$1" -O "$2" 2>&1)
323  _status=$?
324  else
325  get_ciphersuites_for_wget
326  _ciphersuites="$RETVAL"
327  if [ -n "$_ciphersuites" ]; then
328  _err=$(wget --https-only --secure-protocol=TLSv1_2 --ciphers "$_ciphersuites" "$1" -O "$2" 2>&1)
329  _status=$?
330  else
331  echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
332  if ! check_help_for "$3" wget --https-only --secure-protocol; then
333  echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
334  _err=$(wget "$1" -O "$2" 2>&1)
335  _status=$?
336  else
337  _err=$(wget --https-only --secure-protocol=TLSv1_2 "$1" -O "$2" 2>&1)
338  _status=$?
339  fi
340  fi
341  fi
342  if [ -n "$_err" ]; then
343  echo "$_err" >&2
344  if echo "$_err" | grep -q ' 404 Not Found$'; then
345  err "installer for platform '$3' not found, this may be unsupported"
346  fi
347  fi
348  return $_status
349  else
350  err "Unknown downloader" # should not reach here
351  fi
352 }
353 
354 main "$@" || exit 1