Skip to content

Verified downloads#301

Open
tcely wants to merge 9 commits into
openresty:masterfrom
tcely:tcely-docker
Open

Verified downloads#301
tcely wants to merge 9 commits into
openresty:masterfrom
tcely:tcely-docker

Conversation

@tcely
Copy link
Copy Markdown

@tcely tcely commented May 20, 2026

The fallback-to-busybox.sh script is now as fully featured as I plan to make it.

This should be enough for a proof-of-concept that everything works with the provided, or retrieved, sha256 checksums.

I have provided a copy of fallback-to-busybox.sh as a distinct file. This should let you test it with various options outside the Dockerfile and you can also download the 0.6.0 version of asfald to compare those alternatives.

I've tested building this on the supported platforms (linux/amd64, linux/arm64) and tried it with linux/s390x to see the fallback script in action. It all looks good as far as I can tell.

Latest build from my test branch:


TODO:

  • Retrieve the hash from patterns for the fallback
  • Retrieve the GitHub digest from release artifacts in the fallback script

@tcely tcely force-pushed the tcely-docker branch 2 times, most recently from 9020621 to 42b6d4d Compare May 20, 2026 12:20
@neomantra
Copy link
Copy Markdown
Member

I am not going to be merging patchers and checkers like this. I am also OK with validation and scripts that are out-of-band and run either manually or via GitHub Actions. I say this in #299 as well.

But, you did surface that we download the OpenResty source tarball without checksum validation and we can add that like we do for PCRE.

@tcely
Copy link
Copy Markdown
Author

tcely commented May 20, 2026

I am not going to be merging patchers and checkers like this.

I am confused by why you would write that this is a patcher or checker. If curl or wget added the ability to verify what they downloaded, would that somehow be unacceptable?

If you prefer another tool, that's fine. However, you're going to be increasing your own maintenance work if you stick to manually provided hashes and custom verification tools. Whatever alternative you select should really let you take advantage of the digest GitHub added for every artifact last year. It's also helpful to be able to use checksum files upstream projects published before that feature was added.

@neomantra
Copy link
Copy Markdown
Member

What you are saying makes sense, especially with respect to the signatures being there so we should do our best.

When I first read that, I misunderstood what was going on and now understand asfald and --checksum better. Should have waited before looking while in draft.

Is it possible to turn that into a script in /scripts/, so that will be easier to track, scope, and test outside of the Dockerfile?

@tcely
Copy link
Copy Markdown
Author

tcely commented May 20, 2026

Is it possible to turn that into a script in /scripts/, so that will be easier to track, scope, and test outside of the Dockerfile?

We could certainly pull out the fallback script, and create a script to bootstrap asfald binaries from known hashes.

@tcely tcely force-pushed the tcely-docker branch 6 times, most recently from d3e6107 to f129d73 Compare May 22, 2026 08:51
@tcely tcely marked this pull request as ready for review May 22, 2026 09:00
@tcely
Copy link
Copy Markdown
Author

tcely commented May 22, 2026

Is it possible to turn that into a script in /scripts/, so that will be easier to track, scope, and test outside of the Dockerfile?

We could certainly pull out the fallback script, and create a script to bootstrap asfald binaries from known hashes.

A bootstrap script
#!/usr/bin/env sh
set -eu

# Configuration Constants
bootstrap_url='https://github.com/tcely/docker-openresty/raw/1ec3f030398660f0d6b35c6130c1e8540f4364bf/restyrepo/fallback-to-busybox.sh'
bootstrap_hash='efa7d1178ceb3ba7adcce2ba075c6315e40b10e93cec1b92ad9d0f2e3e2da20a'

stderr() {
    busybox printf -- '%s\n' "${@}"
} 1>&2

# Setup Temporary Directory Workspace
work_dir="$(busybox mktemp -d)"
trap 'busybox rm -rf "${work_dir}"' EXIT INT TERM

temp_staging="${work_dir}/asfald"

stderr 'Downloading initial environment bootstrap script...'
if command -v curl >/dev/null 2>&1; then
    curl -fSL -o "${temp_staging}" "${bootstrap_url}"
else
    busybox wget -O "${temp_staging}" "${bootstrap_url}"
fi

# Checksum Validation for the Bootstrap File
stderr 'Confirming script integrity...'
busybox printf '%s *%s\n' "${bootstrap_hash}" "${temp_staging}" | busybox sha256sum -cw

busybox chmod -c +x "${temp_staging}"

# Bootstrap Itself: Run the tool using --output and --hash to install cleanly as 'asfald'
stderr "Using the staging script to safely verify and install itself as './asfald'..."
"${temp_staging}" \
    --hash "${bootstrap_hash}" \
    --output 'asfald' \
    "${bootstrap_url}"

busybox chmod -c +x asfald

resolve_target_os() {
    case "$(uname -s)" in
        (Darwin)  busybox printf -- '%s' 'apple-darwin' ;;
        (Linux)   busybox printf -- '%s' 'linux-musl' ;;
        (FreeBSD) busybox printf -- '%s' 'freebsd' ;;
        (*)       stderr 'Warning: Unsupported OS. Skipping binary downloads.' ;;
    esac
}

resolve_target_arch() {
    case "$(uname -m)" in
        (x86_64|amd64)  busybox printf -- '%s' 'x86_64' ;;
        (arm64|aarch64) busybox printf -- '%s' 'aarch64' ;;
        (armv7*)        busybox printf -- '%s' 'armv7' ;;
        (*)             stderr 'Warning: Unsupported arch. Skipping binary downloads.' ;;
    esac
}

target_os="$(resolve_target_os)"
target_arch="$(resolve_target_arch)"

download_target() {
    url_path="${1}"
    local_name="${2}"
    base_url="https://github.com/asfaload/asfald/releases/${url_path}"

    # Instantly skip if the underlying platform mapping is missing
    if [ -z "${target_os}" ] || [ -z "${target_arch}" ]; then
        return 1
    fi

    stderr 'Discovering platform target via single-pass manifest pipeline...'
    # Evaluates full record ($0) for arch/os and suffix ($NF) for extension exclusion.
    # Blanks the hash column ($1) and removes standard spaces/binary prefixes via single POSIX sub call before printing the full file string.
    asset_name="$(./asfald --output - "${base_url}/checksums.txt" |
        busybox awk -v arch="${target_arch}" -v os="${target_os}" -e '
            $0 ~ arch && $0 ~ os && $NF !~ /\.(tar\.gz|zip)$/ {
                $1 = "";
                sub(/^[ \t]*\*?/, "");
                print;
                exit;
            }
        ')"

    if [ -z "${asset_name}" ]; then
        stderr "Error: Target string isolation failed for ${target_arch}-${target_os} (${base_url})"
        return 1
    fi

    stderr "Downloading ${asset_name} -> ${local_name} using fully native self-verification..."
    if ! ./asfald \
        --pattern '${path}/checksums.txt' \
        --output "${local_name}" \
        "${base_url}/${asset_name}"; then
        stderr "Error: Failed to process validated download for ${asset_name}"
        return 1
    fi

    busybox chmod -c +x "${local_name}"
    return 0
}

# Track Binary Success Status
latest_ok='0'
pinned_ok='0'

stderr '--- Installing Application Binary: asfald-latest ---'
if download_target 'latest/download' 'asfald-latest'; then
    latest_ok='1'
else
    stderr 'Notice: Skipping asfald-latest setup.'
fi

stderr '--- Replacing Downloader Script with Permanent Pinned Binary: asfald (v0.6.0) ---'
if download_target 'download/v0.6.0' 'asfald'; then
    pinned_ok='1'
else
    stderr 'Notice: Skipping pinned binary setup. Retaining verified helper tool script.'
fi

# Dynamically Output Custom Installation Instructions Based on State Results
stderr ''
install_targets=''
_separator='----------------------------------------------------------------------------'

if [ 1 -eq "${pinned_ok}" ]; then install_targets='asfald'; fi
if [ 1 -eq "${latest_ok}" ]; then install_targets="${install_targets:+${install_targets} }asfald-latest"; fi

if [ -n "${install_targets}" ]; then
    stderr 'Finished processing application installation targets.' "${_separator}"
    stderr 'To install successfully retrieved binaries globally on your system path, run:'
    stderr "  sudo busybox install -m 755 ${install_targets} /usr/local/sbin/" "${_separator}"
else
    stderr 'Finished processing toolchain initialization.' "${_separator}"
    stderr 'Notice: Remote static binary downloads are unavailable or unsupported on this host.'
    stderr 'You can still install the verified download script globally by running:'
    stderr '  sudo busybox install -m 755 asfald /usr/local/sbin/' "${_separator}"
fi

@neomantra
Copy link
Copy Markdown
Member

Thanks for this work -- I'm tracking the other CVE and it's a holiday weekend. I will check it out.

tcely added 8 commits May 22, 2026 16:37
This is only for reference, because GitHub generates these archives
rather than reading them.
Generated with:
    $ awk \
        '/^        printf -- ...... ....usr.bin.env sh. .. .$/,/^[ ]+[;] .$/ {print;}' \
        ./restyrepo/Dockerfile | sh | tee ./restyrepo/fallback-to-busybox.sh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants