diff --git a/containers/agent/entrypoint.sh b/containers/agent/entrypoint.sh index 6009940f1..c3caff65e 100644 --- a/containers/agent/entrypoint.sh +++ b/containers/agent/entrypoint.sh @@ -699,6 +699,101 @@ copy_awf_ca_cert() { fi } +copy_system_ca_bundle() { + # Detect and copy the host system CA bundle to a chroot-accessible path. + # On Amazon Linux / RHEL-family systems, the CA bundle lives under /etc/pki/ + # which is not mounted into the chroot. This function finds the system bundle + # and copies it to /tmp/awf-lib/ so TLS works regardless of distro. + # + # In SSL Bump mode, the AWF CA must remain the active trust bundle for MITM + # proxy validation. We only append the system bundle to that staged AWF CA. + SYSTEM_CA_CHROOT="" + + if [ "${AWF_SSL_BUMP_ENABLED}" = "true" ]; then + if [ -z "$AWF_CA_CHROOT" ] || [ ! -f "/host${AWF_CA_CHROOT}" ]; then + echo "[entrypoint][WARN] SSL Bump enabled but chroot AWF CA bundle is unavailable — preserving existing TLS env vars" + return + fi + + # SSL Bump already configured TLS env vars; detect system bundle and append + # it to the AWF CA so tools trust both the AWF proxy CA AND the upstream CAs. + local SYSTEM_BUNDLE="" + for candidate in \ + /host/etc/ssl/certs/ca-certificates.crt \ + /host/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem \ + /host/etc/pki/tls/certs/ca-bundle.crt \ + /host/etc/pki/tls/cert.pem \ + /host/etc/ssl/cert.pem; do + if [ -s "$candidate" ]; then + SYSTEM_BUNDLE="$candidate" + break + fi + done + if [ -n "$SYSTEM_BUNDLE" ]; then + # Append system bundle to the AWF CA cert so both are trusted + if { printf '\n'; cat "$SYSTEM_BUNDLE"; } >> "/host${AWF_CA_CHROOT}" 2>/dev/null; then + echo "[entrypoint] System CA bundle ($SYSTEM_BUNDLE) appended to AWF CA cert" + fi + fi + return + fi + + # No SSL Bump — detect and expose the system CA bundle for chroot. + local SYSTEM_BUNDLE="" + for candidate in \ + /host/etc/ssl/certs/ca-certificates.crt \ + /host/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem \ + /host/etc/pki/tls/certs/ca-bundle.crt \ + /host/etc/pki/tls/cert.pem \ + /host/etc/ssl/cert.pem; do + if [ -s "$candidate" ]; then + SYSTEM_BUNDLE="$candidate" + break + fi + done + + if [ -z "$SYSTEM_BUNDLE" ]; then + echo "[entrypoint][WARN] No system CA bundle found — TLS may fail inside chroot" + return + fi + + # Check if the bundle is already accessible inside the chroot via existing mounts. + # AWF mounts /etc/ssl and /etc/ca-certificates into the chroot; paths under those + # prefixes are already visible. Paths under /etc/pki (RHEL/Amazon Linux) are not. + local CHROOT_RELATIVE="${SYSTEM_BUNDLE#/host}" + case "$CHROOT_RELATIVE" in + /etc/ssl/*|/etc/ca-certificates/*) + # Already accessible via existing bind mounts + export SSL_CERT_FILE="$CHROOT_RELATIVE" + export NODE_EXTRA_CA_CERTS="$CHROOT_RELATIVE" + export REQUESTS_CA_BUNDLE="$CHROOT_RELATIVE" + export CURL_CA_BUNDLE="$CHROOT_RELATIVE" + export GIT_SSL_CAINFO="$CHROOT_RELATIVE" + echo "[entrypoint] System CA bundle found at $CHROOT_RELATIVE (already accessible in chroot)" + return + ;; + esac + + # Bundle is not accessible in chroot (e.g., /etc/pki paths). Copy it. + if mkdir -p /host/tmp/awf-lib 2>/dev/null; then + if cp "$SYSTEM_BUNDLE" /host/tmp/awf-lib/system-ca-certificates.crt 2>/dev/null && \ + [ -s /host/tmp/awf-lib/system-ca-certificates.crt ]; then + local CA_PATH="/tmp/awf-lib/system-ca-certificates.crt" + SYSTEM_CA_CHROOT="$CA_PATH" + export SSL_CERT_FILE="$CA_PATH" + export NODE_EXTRA_CA_CERTS="$CA_PATH" + export REQUESTS_CA_BUNDLE="$CA_PATH" + export CURL_CA_BUNDLE="$CA_PATH" + export GIT_SSL_CAINFO="$CA_PATH" + echo "[entrypoint] System CA bundle copied from $SYSTEM_BUNDLE to $CA_PATH" + else + echo "[entrypoint][WARN] Could not copy system CA bundle to chroot — TLS may fail" + fi + else + echo "[entrypoint][WARN] Could not create /host/tmp/awf-lib for system CA bundle" + fi +} + check_chroot_prereqs() { # Verify prerequisites for chroot execution: glibc-based host, capsh, and bash. # Each check fails fast with exit 1 on failure. @@ -1109,6 +1204,7 @@ run_chroot_command() { copy_agent_helper_scripts copy_dind_runner_binary copy_awf_ca_cert + copy_system_ca_bundle setup_chroot_etc # Determine working directory inside the chroot @@ -1165,7 +1261,7 @@ run_chroot_command() { echo "[entrypoint] host.docker.internal will be removed from /etc/hosts on exit" fi # Clean up /tmp/awf-lib if anything was copied (one-shot-token, CA cert, key helper) - if [ -n "${ONE_SHOT_TOKEN_LIB}" ] || [ -n "${AWF_CA_CHROOT}" ] || [ -n "${CHROOT_KEY_HELPER}" ] || [ -n "${STAGED_RUNNER_BINARY_CHROOT}" ]; then + if [ -n "${ONE_SHOT_TOKEN_LIB}" ] || [ -n "${AWF_CA_CHROOT}" ] || [ -n "${SYSTEM_CA_CHROOT}" ] || [ -n "${CHROOT_KEY_HELPER}" ] || [ -n "${STAGED_RUNNER_BINARY_CHROOT}" ]; then CLEANUP_CMD="${CLEANUP_CMD}; rm -rf /tmp/awf-lib 2>/dev/null || true" fi diff --git a/docs/chroot-mode.md b/docs/chroot-mode.md index 52901f052..d8650c6e4 100644 --- a/docs/chroot-mode.md +++ b/docs/chroot-mode.md @@ -191,6 +191,8 @@ When `chroot.binariesSourcePath` is set in stdin config, AWF also mounts: **Note:** As of v0.13.13, `/proc` is no longer bind-mounted. Instead, a fresh container-scoped procfs is mounted at `/host/proc` during entrypoint initialization. This provides dynamic `/proc/self/exe` resolution required by Java and .NET runtimes. +**System CA Bundle Detection:** The entrypoint automatically detects the host system CA bundle from common locations (Debian/Ubuntu `/etc/ssl/certs/ca-certificates.crt`, RHEL/Amazon Linux `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem`, `/etc/pki/tls/certs/ca-bundle.crt`, `/etc/pki/tls/cert.pem`, macOS `/etc/ssl/cert.pem`). If the bundle is not already accessible in the chroot via existing mounts (e.g., `/etc/pki` paths), it is copied to `/tmp/awf-lib/system-ca-certificates.crt` and `SSL_CERT_FILE`, `NODE_EXTRA_CA_CERTS`, `REQUESTS_CA_BUNDLE`, `CURL_CA_BUNDLE`, and `GIT_SSL_CAINFO` are set to point at it. + ### Read-Write Mounts | Host Path | Container Path | Purpose | diff --git a/tests/entrypoint-phase-functions.test.sh b/tests/entrypoint-phase-functions.test.sh index b68dfbf33..f8178870d 100755 --- a/tests/entrypoint-phase-functions.test.sh +++ b/tests/entrypoint-phase-functions.test.sh @@ -31,6 +31,7 @@ required_functions=( copy_agent_helper_scripts copy_dind_runner_binary copy_awf_ca_cert + copy_system_ca_bundle check_chroot_prereqs setup_chroot_etc build_path_script @@ -102,6 +103,12 @@ CHROOT_BLOCK="$(awk ' in_fn { print } ' "${ENTRYPOINT}")" +COPY_SYSTEM_CA_BUNDLE_BLOCK="$(awk ' + /^[[:space:]]*copy_system_ca_bundle\(\)[[:space:]]*\{[[:space:]]*$/ { in_fn=1; next } + in_fn && /^[[:space:]]*}[[:space:]]*$/ { in_fn=0; exit } + in_fn { print } +' "${ENTRYPOINT}")" + chroot_helpers=( 'mount_host_procfs' 'check_chroot_prereqs' @@ -109,6 +116,7 @@ chroot_helpers=( 'copy_agent_helper_scripts' 'copy_dind_runner_binary' 'copy_awf_ca_cert' + 'copy_system_ca_bundle' 'setup_chroot_etc' 'build_path_script' ) @@ -128,6 +136,25 @@ for helper in "${chroot_helpers[@]}"; do pass "run_chroot_command() calls ${helper} in order" done +if printf '%s\n' "${COPY_SYSTEM_CA_BUNDLE_BLOCK}" | grep -Fq 'if [ "${AWF_SSL_BUMP_ENABLED}" = "true" ]'; then + pass "copy_system_ca_bundle() keys SSL Bump handling off AWF_SSL_BUMP_ENABLED" +else + fail "copy_system_ca_bundle() does not key SSL Bump handling off AWF_SSL_BUMP_ENABLED" +fi + +if printf '%s\n' "${COPY_SYSTEM_CA_BUNDLE_BLOCK}" | grep -Fq "printf '\\n'" && \ + printf '%s\n' "${COPY_SYSTEM_CA_BUNDLE_BLOCK}" | grep -Fq '"/host${AWF_CA_CHROOT}"'; then + pass "copy_system_ca_bundle() appends system roots to the staged AWF CA bundle safely" +else + fail "copy_system_ca_bundle() does not safely append system roots to the staged AWF CA bundle" +fi + +if grep -Eq '\[ -n "\$\{SYSTEM_CA_CHROOT\}" \]' "${ENTRYPOINT}"; then + pass "run_chroot_command() cleans up copied system CA bundles" +else + fail "run_chroot_command() does not clean up copied system CA bundles" +fi + echo "" echo "Results: ${PASS} passed, ${FAIL} failed"