e0e362d700
SDK Tests / SDK CI (push) Blocked by required conditions
SDK Tests / changes (push) Successful in 2m29s
Real E2E Tests / changes (push) Successful in 2m29s
SDK Tests / Python SDK Tests (sandbox) (push) Waiting to run
SDK Tests / CLI Quality (push) Waiting to run
SDK Tests / CLI Tests (push) Waiting to run
SDK Tests / Python SDK Quality (code-interpreter) (push) Waiting to run
SDK Tests / Python SDK Quality (sandbox) (push) Waiting to run
SDK Tests / Python SDK Tests (code-interpreter) (push) Waiting to run
SDK Tests / JavaScript SDK Quality And Tests (code-interpreter) (push) Waiting to run
SDK Tests / JavaScript SDK Quality And Tests (sandbox) (push) Waiting to run
SDK Tests / Kotlin SDK Quality And Tests (sandbox) (push) Waiting to run
SDK Tests / Kotlin SDK Quality And Tests (code-interpreter) (push) Waiting to run
SDK Tests / C# SDK Quality And Tests (code-interpreter) (push) Waiting to run
SDK Tests / C# SDK Quality And Tests (sandbox) (push) Waiting to run
SDK Tests / Go SDK Quality And Tests (push) Waiting to run
Deploy Docs Pages / build (push) Has been cancelled
Deploy Docs Pages / deploy (push) Has been cancelled
Real E2E Tests / JavaScript E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Python E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Java E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / C# E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Go E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Real E2E CI (push) Has been cancelled
337 lines
10 KiB
Bash
Executable File
337 lines
10 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# Copyright 2025 Alibaba Group Holding Ltd.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
set -e
|
|
|
|
_forward_signal() {
|
|
sig="$1"
|
|
pid="$2"
|
|
kill "-$sig" "$pid" 2>/dev/null || true
|
|
wait "$pid" 2>/dev/null || true
|
|
exit 0
|
|
}
|
|
|
|
# Returns 0 if the value looks like a boolean "true" (1, true, yes, on).
|
|
is_truthy() {
|
|
case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in
|
|
1 | true | yes | on) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
_sudo() {
|
|
if [ "$(id -u)" -eq 0 ]; then
|
|
"$@"
|
|
elif command -v sudo >/dev/null 2>&1; then
|
|
sudo -n "$@"
|
|
else
|
|
"$@"
|
|
fi
|
|
}
|
|
|
|
# Install mitm CA into the system trust store (for non-Python programs)
|
|
# and set OPENSANDBOX_MERGED_CA to a PEM bundle containing a full root
|
|
# set + mitm CA (for env vars like REQUESTS_CA_BUNDLE that *replace*
|
|
# rather than append to the default roots).
|
|
OPENSANDBOX_MERGED_CA=""
|
|
trust_mitm_ca() {
|
|
cert="$1"
|
|
merged="/opt/opensandbox/merged-ca-certificates.pem"
|
|
|
|
# 1) Try to install into the system trust store (best-effort).
|
|
if command -v update-ca-certificates >/dev/null 2>&1; then
|
|
_sudo mkdir -p /usr/local/share/ca-certificates \
|
|
&& _sudo cp "$cert" /usr/local/share/ca-certificates/opensandbox-mitmproxy-ca.crt \
|
|
&& _sudo update-ca-certificates \
|
|
|| echo "warning: update-ca-certificates failed; system trust store may not include mitm CA" >&2
|
|
elif command -v update-ca-trust >/dev/null 2>&1; then
|
|
_sudo mkdir -p /etc/pki/ca-trust/source/anchors \
|
|
&& _sudo cp "$cert" /etc/pki/ca-trust/source/anchors/opensandbox-mitmproxy-ca.pem \
|
|
&& { _sudo update-ca-trust extract || _sudo update-ca-trust; } \
|
|
|| echo "warning: update-ca-trust failed; system trust store may not include mitm CA" >&2
|
|
else
|
|
echo "warning: no system trust-store tooling found (need update-ca-certificates or update-ca-trust)" >&2
|
|
fi
|
|
|
|
# 2) Build a merged bundle (complete root set + mitm CA).
|
|
# Prefer certifi (full Mozilla root set) over system bundles which
|
|
# may be incomplete in minimal Docker images.
|
|
certifi_ca=""
|
|
if command -v python3 >/dev/null 2>&1; then
|
|
certifi_ca="$(python3 -c 'import certifi; print(certifi.where())' 2>/dev/null)" || certifi_ca=""
|
|
elif command -v python >/dev/null 2>&1; then
|
|
certifi_ca="$(python -c 'import certifi; print(certifi.where())' 2>/dev/null)" || certifi_ca=""
|
|
fi
|
|
|
|
for candidate in \
|
|
"$certifi_ca" \
|
|
/etc/ssl/certs/ca-certificates.crt \
|
|
/etc/pki/tls/certs/ca-bundle.crt \
|
|
/etc/ssl/cert.pem \
|
|
/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem; do
|
|
if [ -n "$candidate" ] && [ -f "$candidate" ] && [ -s "$candidate" ]; then
|
|
cat "$candidate" "$cert" > "$merged"
|
|
OPENSANDBOX_MERGED_CA="$merged"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
echo "warning: could not locate any CA bundle to merge with mitm CA" >&2
|
|
return 0
|
|
}
|
|
|
|
# Chromium/Chrome on Linux do not use only the system trust store: they also honor the per-user
|
|
# NSS database at $HOME/.pki/nssdb. Import the same mitm CA there so the browser trusts it.
|
|
# Requires certutil (e.g. Alpine: nss-tools, Debian/Ubuntu: libnss3-tools).
|
|
trust_mitm_ca_nss() {
|
|
cert="$1"
|
|
[ -f "$cert" ] || return 0
|
|
[ -n "${HOME:-}" ] && [ -d "$HOME" ] || return 0
|
|
if ! command -v certutil >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
pki="${HOME}/.pki/nssdb"
|
|
if ! mkdir -p "$pki" 2>/dev/null; then
|
|
return 0
|
|
fi
|
|
if [ -f "$pki/cert9.db" ]; then
|
|
nssdb="sql:$pki"
|
|
elif [ -f "$pki/cert8.db" ]; then
|
|
nssdb="dbm:$pki"
|
|
else
|
|
nssdb="sql:$pki"
|
|
if ! certutil -N -d "$nssdb" --empty-password 2>/dev/null; then
|
|
[ -f "$pki/cert9.db" ] || return 0
|
|
fi
|
|
fi
|
|
nick="opensandbox-mitmproxy"
|
|
certutil -D -d "$nssdb" -n "$nick" 2>/dev/null || true
|
|
if ! certutil -A -d "$nssdb" -n "$nick" -t "C,," -i "$cert"; then
|
|
echo "warning: failed to import mitm CA into NSS at $pki (Chrome may still distrust); need certutil" >&2
|
|
return 0
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# Import the mitm CA into every JDK trust store found on the system so that Java
|
|
# tooling (Maven, Gradle, HttpClient) trusts the credential-proxy MITM cert.
|
|
# Best-effort: missing keytool or import failure only warns, never blocks.
|
|
_jdk_import_ca() {
|
|
jh="$1"
|
|
cert="$2"
|
|
kt="$jh/bin/keytool"
|
|
[ -x "$kt" ] || return 0
|
|
|
|
alias_name="opensandbox-mitmproxy"
|
|
|
|
# Locate the cacerts keystore — JDK 9+ supports -cacerts flag,
|
|
# JDK 8 and some vendors require an explicit -keystore path.
|
|
ks=""
|
|
if [ -f "$jh/lib/security/cacerts" ]; then
|
|
ks="$jh/lib/security/cacerts"
|
|
elif [ -f "$jh/jre/lib/security/cacerts" ]; then
|
|
ks="$jh/jre/lib/security/cacerts"
|
|
else
|
|
return 0
|
|
fi
|
|
|
|
# Remove stale alias first so a regenerated CA cert is always picked up.
|
|
if "$kt" -list -alias "$alias_name" -keystore "$ks" -storepass changeit >/dev/null 2>&1; then
|
|
_sudo "$kt" -delete -alias "$alias_name" -keystore "$ks" -storepass changeit >/dev/null 2>&1
|
|
fi
|
|
|
|
if _sudo "$kt" -importcert -noprompt -trustcacerts \
|
|
-alias "$alias_name" \
|
|
-file "$cert" \
|
|
-keystore "$ks" \
|
|
-storepass changeit >/dev/null 2>&1; then
|
|
echo "imported mitm CA into JDK trust store at $ks"
|
|
else
|
|
echo "warning: failed to import mitm CA into $ks" >&2
|
|
fi
|
|
}
|
|
|
|
_SEEN_JDKS=""
|
|
_try_jdk() {
|
|
candidate="$1"
|
|
cert="$2"
|
|
[ -d "$candidate" ] || return 0
|
|
# Resolve to real path for dedup (POSIX: cd + pwd -P).
|
|
real="$(cd "$candidate" 2>/dev/null && pwd -P)" || return 0
|
|
case " $_SEEN_JDKS " in
|
|
*" $real "*) return 0 ;;
|
|
esac
|
|
_SEEN_JDKS="$_SEEN_JDKS $real"
|
|
_jdk_import_ca "$real" "$cert"
|
|
}
|
|
|
|
trust_mitm_ca_jdk() {
|
|
cert="$1"
|
|
[ -f "$cert" ] || return 0
|
|
_SEEN_JDKS=""
|
|
|
|
# 1) $JAVA_HOME if set.
|
|
if [ -n "${JAVA_HOME:-}" ]; then
|
|
_try_jdk "$JAVA_HOME" "$cert"
|
|
fi
|
|
|
|
# 2) Scan well-known JDK directories.
|
|
for search_dir in /usr/lib/jvm /usr/java /opt/java; do
|
|
if [ -d "$search_dir" ]; then
|
|
for d in "$search_dir"/*/; do
|
|
[ -d "$d" ] && _try_jdk "${d%/}" "$cert"
|
|
done
|
|
fi
|
|
done
|
|
# Standalone tarball installs (e.g. /opt/jdk, /opt/jdk-21).
|
|
for d in /opt/jdk*; do
|
|
[ -d "$d" ] && _try_jdk "$d" "$cert"
|
|
done
|
|
|
|
# 3) Fallback: resolve `java` on PATH to its JAVA_HOME.
|
|
if command -v java >/dev/null 2>&1; then
|
|
java_bin="$(command -v java)"
|
|
# Follow symlinks (POSIX-portable loop).
|
|
while [ -L "$java_bin" ]; do
|
|
link_target="$(ls -l "$java_bin" 2>/dev/null | sed 's/.* -> //')"
|
|
case "$link_target" in
|
|
/*) java_bin="$link_target" ;;
|
|
*) java_bin="$(dirname "$java_bin")/$link_target" ;;
|
|
esac
|
|
done
|
|
# java_bin is now e.g. /usr/lib/jvm/java-17/bin/java → JAVA_HOME = grandparent
|
|
jh_candidate="$(dirname "$(dirname "$java_bin")")"
|
|
_try_jdk "$jh_candidate" "$cert"
|
|
fi
|
|
|
|
_SEEN_JDKS=""
|
|
return 0
|
|
}
|
|
|
|
MITM_CA="/opt/opensandbox/mitmproxy-ca-cert.pem"
|
|
if is_truthy "${OPENSANDBOX_EGRESS_MITMPROXY_TRANSPARENT:-}"; then
|
|
i=0
|
|
while [ "$i" -lt 300 ]; do
|
|
if [ -f "$MITM_CA" ] && [ -s "$MITM_CA" ]; then
|
|
break
|
|
fi
|
|
sleep 1
|
|
i=$((i + 1))
|
|
done
|
|
if [ ! -f "$MITM_CA" ] || [ ! -s "$MITM_CA" ]; then
|
|
echo "warning: timed out after 300s waiting for $MITM_CA (egress mitm CA export); continuing without system CA trust" >&2
|
|
else
|
|
echo "mitm CA ready at $MITM_CA after ${i}s"
|
|
if ! trust_mitm_ca "$MITM_CA"; then
|
|
echo "warning: failed to install mitm CA into system trust store; TLS interception may not work for system libraries" >&2
|
|
fi
|
|
fi
|
|
|
|
if [ -f "$MITM_CA" ] && [ -s "$MITM_CA" ]; then
|
|
trust_mitm_ca_nss "$MITM_CA" || true
|
|
trust_mitm_ca_jdk "$MITM_CA" || true
|
|
export NODE_EXTRA_CA_CERTS="$MITM_CA" # additive — Node appends to built-in roots
|
|
|
|
# REQUESTS_CA_BUNDLE and SSL_CERT_FILE replace the default bundle,
|
|
# so use merged roots (certifi/system CA + mitm CA).
|
|
if [ -n "$OPENSANDBOX_MERGED_CA" ] && [ -f "$OPENSANDBOX_MERGED_CA" ]; then
|
|
export REQUESTS_CA_BUNDLE="$OPENSANDBOX_MERGED_CA"
|
|
export SSL_CERT_FILE="$OPENSANDBOX_MERGED_CA"
|
|
else
|
|
echo "warning: merged CA bundle not available; REQUESTS_CA_BUNDLE/SSL_CERT_FILE will only contain the mitm CA" >&2
|
|
export REQUESTS_CA_BUNDLE="$MITM_CA"
|
|
export SSL_CERT_FILE="$MITM_CA"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
EXECD="${EXECD:=/opt/opensandbox/execd}"
|
|
|
|
if [ -z "${EXECD_ENVS:-}" ]; then
|
|
EXECD_ENVS="/opt/opensandbox/.env"
|
|
fi
|
|
if ! mkdir -p "$(dirname "$EXECD_ENVS")" 2>/dev/null; then
|
|
echo "warning: failed to create dir for EXECD_ENVS=$EXECD_ENVS" >&2
|
|
fi
|
|
if ! touch "$EXECD_ENVS" 2>/dev/null; then
|
|
echo "warning: failed to touch EXECD_ENVS=$EXECD_ENVS" >&2
|
|
fi
|
|
export EXECD_ENVS
|
|
|
|
# Run a user-defined pre-script before launching execd. The script is sourced
|
|
# with POSIX `.` (not executed as a child process) so any variables it
|
|
# `export`s propagate to execd and the chained command below — a subprocess
|
|
# would lose those exports the moment it exits.
|
|
if [ -n "${EXECD_BOOTSTRAP_PRE_SCRIPT:-}" ]; then
|
|
if [ -f "$EXECD_BOOTSTRAP_PRE_SCRIPT" ] && [ -r "$EXECD_BOOTSTRAP_PRE_SCRIPT" ]; then
|
|
# Force `.` to read the literal path; without a slash it would fall
|
|
# back to a PATH search and could load the wrong file.
|
|
case "$EXECD_BOOTSTRAP_PRE_SCRIPT" in
|
|
*/*) _pre_script="$EXECD_BOOTSTRAP_PRE_SCRIPT" ;;
|
|
*) _pre_script="./$EXECD_BOOTSTRAP_PRE_SCRIPT" ;;
|
|
esac
|
|
echo "sourcing pre-script $EXECD_BOOTSTRAP_PRE_SCRIPT"
|
|
# shellcheck disable=SC1090
|
|
. "$_pre_script"
|
|
unset _pre_script
|
|
else
|
|
echo "warning: EXECD_BOOTSTRAP_PRE_SCRIPT=$EXECD_BOOTSTRAP_PRE_SCRIPT not found or not readable" >&2
|
|
fi
|
|
fi
|
|
|
|
echo "starting OpenSandbox Execd daemon at $EXECD."
|
|
$EXECD &
|
|
|
|
# Allow chained shell commands (e.g., /test1.sh && /test2.sh)
|
|
# Usage:
|
|
# bootstrap.sh -c "/test1.sh && /test2.sh"
|
|
# Or set BOOTSTRAP_CMD="/test1.sh && /test2.sh"
|
|
CMD=""
|
|
if [ "${BOOTSTRAP_CMD:-}" != "" ]; then
|
|
CMD="$BOOTSTRAP_CMD"
|
|
elif [ $# -ge 1 ] && [ "$1" = "-c" ]; then
|
|
shift
|
|
CMD="$*"
|
|
fi
|
|
|
|
SHELL_BIN="${BOOTSTRAP_SHELL:-}"
|
|
if [ -z "$SHELL_BIN" ]; then
|
|
if command -v bash >/dev/null 2>&1; then
|
|
SHELL_BIN="$(command -v bash)"
|
|
elif command -v sh >/dev/null 2>&1; then
|
|
SHELL_BIN="$(command -v sh)"
|
|
else
|
|
echo "error: neither bash nor sh found in PATH" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ "$CMD" != "" ]; then
|
|
"$SHELL_BIN" -c "$CMD" &
|
|
CMD_PID=$!
|
|
elif [ $# -eq 0 ]; then
|
|
"$SHELL_BIN" &
|
|
CMD_PID=$!
|
|
else
|
|
"$@" &
|
|
CMD_PID=$!
|
|
fi
|
|
|
|
trap '_forward_signal TERM "$CMD_PID"' TERM
|
|
|
|
wait "$CMD_PID" 2>/dev/null
|
|
exit $?
|