mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-09 12:40:20 +08:00
Consolidate subscription usage policy enforcement, privacy-safe persistence, and gateway security hardening into one reviewable change. Includes bounded HTTP and execution envelopes, header and protocol guards, DNS and relay validation, authentication and secret projection hardening, secure backup/install paths, and regression coverage.
222 lines
11 KiB
Bash
Executable File
222 lines
11 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
|
INSTALLER="${REPO_ROOT}/apps/aether-tunnel/install.sh"
|
|
POWERSHELL_INSTALLER="${REPO_ROOT}/apps/aether-tunnel/install.ps1"
|
|
TEST_ROOT="${REPO_ROOT}/.tmp-tunnel-installer-test.$$"
|
|
|
|
cleanup_test_root() {
|
|
chmod -R u+rwX "${TEST_ROOT}" 2>/dev/null || true
|
|
rm -rf -- "${TEST_ROOT}"
|
|
}
|
|
trap cleanup_test_root EXIT
|
|
|
|
fail_test() {
|
|
echo "FAIL: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
assert_rejected() {
|
|
if ("$@") >/dev/null 2>&1; then
|
|
fail_test "unsafe installer fixture was accepted: $*"
|
|
fi
|
|
}
|
|
|
|
file_mode() {
|
|
stat -c '%a' "$1" 2>/dev/null || stat -f '%Lp' "$1"
|
|
}
|
|
|
|
mkdir -m 700 "${TEST_ROOT}"
|
|
LIB="${TEST_ROOT}/installer-lib.sh"
|
|
sed '/^main()/,$d' "${INSTALLER}" >"${LIB}"
|
|
# shellcheck source=/dev/null
|
|
source "${LIB}"
|
|
trap cleanup_test_root EXIT
|
|
|
|
validate_release_repo "fawney19/Aether"
|
|
validate_tunnel_release_tag "tunnel-v0.3.16-rc.1"
|
|
validate_tunnel_release_tag "tunnel-v1.2.3+build.7"
|
|
validate_release_asset_name "aether-tunnel-linux-amd64.tar.gz"
|
|
validate_node_name "Tokyo edge 01"
|
|
validate_node_name "东京节点"
|
|
assert_rejected validate_release_repo "owner/repo/extra"
|
|
assert_rejected validate_release_repo 'owner/repo;touch injected'
|
|
assert_rejected validate_tunnel_release_tag "../tunnel-v0.3.16"
|
|
assert_rejected validate_tunnel_release_tag "gateway-v0.3.16"
|
|
assert_rejected validate_tunnel_release_tag "tunnel-v1.2"
|
|
assert_rejected validate_tunnel_release_tag "tunnel-v01.2.3"
|
|
assert_rejected validate_tunnel_release_tag "tunnel-v1.2.3-01"
|
|
assert_rejected validate_release_asset_name "../aether-tunnel-linux-amd64.tar.gz"
|
|
assert_rejected validate_node_name " trailing "
|
|
assert_rejected validate_node_name $'node\tname'
|
|
assert_rejected validate_node_name $'node\nname'
|
|
assert_rejected validate_node_name "$(printf 'n%.0s' {1..256})"
|
|
|
|
assert_rejected validate_https_download_url "http://example.test/release.tar.gz"
|
|
assert_rejected validate_https_download_url "https://user:pass@example.test/release.tar.gz"
|
|
assert_rejected validate_https_download_url "https://example.test/release.tar.gz#fragment"
|
|
validate_trusted_github_download_url "https://github.com/fawney19/Aether/releases/download/tunnel-v1.2.3/aether-tunnel-linux-amd64.tar.gz"
|
|
validate_trusted_github_download_url "https://release-assets.githubusercontent.com/example/object"
|
|
assert_rejected validate_trusted_github_download_url "https://github.com.evil.example/release.tar.gz"
|
|
assert_rejected validate_trusted_github_download_url "https://github.com:444/release.tar.gz"
|
|
|
|
CURL_ARGS="${TEST_ROOT}/curl-args"
|
|
curl() {
|
|
printf '%s\n' "$@" >"${CURL_ARGS}"
|
|
local headers='' output='' url=''
|
|
while (($#)); do
|
|
case "$1" in
|
|
--dump-header) headers="$2"; shift 2 ;;
|
|
--output) output="$2"; shift 2 ;;
|
|
--write-out) shift 2 ;;
|
|
-*) shift ;;
|
|
*) url="$1"; shift ;;
|
|
esac
|
|
done
|
|
: >"${headers}"
|
|
printf '%s\n' "verified download from ${url}" >"${output}"
|
|
printf '200'
|
|
}
|
|
download "https://github.com/fawney19/Aether/release.tar.gz" "${TEST_ROOT}/downloaded"
|
|
grep -Fxq -- '--proto' "${CURL_ARGS}" || fail_test "curl HTTPS protocol restriction is missing"
|
|
grep -Fxq -- '=https' "${CURL_ARGS}" || fail_test "curl HTTPS protocol value is missing"
|
|
grep -Fxq -- '--max-redirs' "${CURL_ARGS}" || fail_test "curl automatic redirects were not disabled"
|
|
unset -f curl
|
|
|
|
checksum_asset="aether-tunnel-linux-amd64.tar.gz"
|
|
checksum_archive="${TEST_ROOT}/${checksum_asset}"
|
|
checksum_manifest="${TEST_ROOT}/SHA256SUMS.txt"
|
|
printf '%s\n' "verified release payload" >"${checksum_archive}"
|
|
if command -v sha256sum >/dev/null 2>&1; then
|
|
checksum="$(sha256sum "${checksum_archive}" | awk '{print $1}')"
|
|
else
|
|
checksum="$(shasum -a 256 "${checksum_archive}" | awk '{print $1}')"
|
|
fi
|
|
printf '%s %s\n' "${checksum}" "${checksum_asset}" >"${checksum_manifest}"
|
|
verify_checksum "${checksum_archive}" "${checksum_manifest}" "${checksum_asset}"
|
|
printf '%064d %s\n' 0 "${checksum_asset}" >"${checksum_manifest}"
|
|
assert_rejected verify_checksum "${checksum_archive}" "${checksum_manifest}" "${checksum_asset}"
|
|
printf '%063d %s\n' 0 "${checksum_asset}" >"${checksum_manifest}"
|
|
assert_rejected verify_checksum "${checksum_archive}" "${checksum_manifest}" "${checksum_asset}"
|
|
printf '%s %s\n' "${checksum}" "other-asset.tar.gz" >"${checksum_manifest}"
|
|
assert_rejected verify_checksum "${checksum_archive}" "${checksum_manifest}" "${checksum_asset}"
|
|
printf '%s %s trailing-field\n' "${checksum}" "${checksum_asset}" >"${checksum_manifest}"
|
|
assert_rejected verify_checksum "${checksum_archive}" "${checksum_manifest}" "${checksum_asset}"
|
|
printf '%s extra-field %s\n' "${checksum}" "${checksum_asset}" >"${checksum_manifest}"
|
|
assert_rejected verify_checksum "${checksum_archive}" "${checksum_manifest}" "${checksum_asset}"
|
|
printf '%s %s\n%s *%s\n' \
|
|
"${checksum}" "${checksum_asset}" "${checksum}" "${checksum_asset}" >"${checksum_manifest}"
|
|
assert_rejected verify_checksum "${checksum_archive}" "${checksum_manifest}" "${checksum_asset}"
|
|
|
|
CONFIG_PATH="${TEST_ROOT}/normal/aether-tunnel.toml"
|
|
append_server_config "https://aether.example" "secret-token" "node-one" "off" ""
|
|
[[ "$(file_mode "${CONFIG_PATH}")" == "600" ]] || fail_test "config mode is not 0600"
|
|
grep -Fq 'management_token = "secret-token"' "${CONFIG_PATH}" || fail_test "config block was not written"
|
|
|
|
source_binary="${TEST_ROOT}/source-aether-tunnel"
|
|
printf '#!/bin/sh\nexit 0\n' >"${source_binary}"
|
|
chmod 755 "${source_binary}"
|
|
INSTALL_DIR="${TEST_ROOT}/install-bin"
|
|
install_tunnel_binary_file "${source_binary}"
|
|
[[ -x "${INSTALL_DIR}/aether-tunnel" ]] || fail_test "tunnel binary was not installed"
|
|
|
|
binary_victim="${TEST_ROOT}/binary-victim"
|
|
printf '%s\n' "keep-binary-victim" >"${binary_victim}"
|
|
rm -f "${INSTALL_DIR}/aether-tunnel"
|
|
ln -s "${binary_victim}" "${INSTALL_DIR}/aether-tunnel"
|
|
if (install_tunnel_binary_file "${source_binary}") 2>/dev/null; then
|
|
fail_test "symbolic-link binary target was accepted"
|
|
fi
|
|
[[ "$(cat "${binary_victim}")" == "keep-binary-victim" ]] \
|
|
|| fail_test "symbolic-link binary target was modified"
|
|
|
|
rm -f "${INSTALL_DIR}/aether-tunnel"
|
|
binary_hardlink_victim="${TEST_ROOT}/binary-hardlink-victim"
|
|
printf '%s\n' "keep-hardlink-victim" >"${binary_hardlink_victim}"
|
|
ln "${binary_hardlink_victim}" "${INSTALL_DIR}/aether-tunnel"
|
|
if (install_tunnel_binary_file "${source_binary}") 2>/dev/null; then
|
|
fail_test "hard-linked binary target was accepted"
|
|
fi
|
|
[[ "$(cat "${binary_hardlink_victim}")" == "keep-hardlink-victim" ]] \
|
|
|| fail_test "hard-linked binary victim was modified"
|
|
|
|
linked_install_target="${TEST_ROOT}/linked-install-target"
|
|
mkdir -m 700 "${linked_install_target}"
|
|
INSTALL_DIR="${TEST_ROOT}/linked-install-dir"
|
|
ln -s "${linked_install_target}" "${INSTALL_DIR}"
|
|
if (install_tunnel_binary_file "${source_binary}") 2>/dev/null; then
|
|
fail_test "symbolic-link install directory was accepted"
|
|
fi
|
|
[[ ! -e "${linked_install_target}/aether-tunnel" ]] \
|
|
|| fail_test "symbolic-link install directory target was modified"
|
|
|
|
ancestor_target="${TEST_ROOT}/ancestor-target"
|
|
mkdir -m 700 "${ancestor_target}"
|
|
ancestor_link="${TEST_ROOT}/ancestor-link"
|
|
ln -s "${ancestor_target}" "${ancestor_link}"
|
|
INSTALL_DIR="${ancestor_link}/nested/bin"
|
|
if (install_tunnel_binary_file "${source_binary}") 2>/dev/null; then
|
|
fail_test "symbolic-link install ancestor was accepted"
|
|
fi
|
|
[[ ! -e "${ancestor_target}/nested/bin/aether-tunnel" ]] \
|
|
|| fail_test "symbolic-link install ancestor target was modified"
|
|
|
|
chmod 644 "${CONFIG_PATH}"
|
|
append_server_config "https://aether.example" "second-token" "node-two" "off" ""
|
|
[[ "$(file_mode "${CONFIG_PATH}")" == "600" ]] || fail_test "existing config was not protected before update"
|
|
backup="$(find "$(dirname "${CONFIG_PATH}")" -maxdepth 1 -type f -name 'aether-tunnel.toml.bak.*' | head -n1)"
|
|
[[ -n "${backup}" && "$(file_mode "${backup}")" == "600" ]] || fail_test "backup mode is not 0600"
|
|
|
|
victim="${TEST_ROOT}/victim.txt"
|
|
printf '%s\n' "keep-me" >"${victim}"
|
|
CONFIG_PATH="${TEST_ROOT}/linked.toml"
|
|
ln -s "${victim}" "${CONFIG_PATH}"
|
|
if (append_server_config "https://aether.example" "stolen-token" "node-link" "off" "") 2>/dev/null; then
|
|
fail_test "symbolic-link config was accepted"
|
|
fi
|
|
[[ "$(cat "${victim}")" == "keep-me" ]] || fail_test "symbolic-link target was modified"
|
|
|
|
hardlink_victim="${TEST_ROOT}/hardlink-victim.toml"
|
|
printf '%s\n' 'victim = true' >"${hardlink_victim}"
|
|
CONFIG_PATH="${TEST_ROOT}/hardlinked.toml"
|
|
ln "${hardlink_victim}" "${CONFIG_PATH}"
|
|
if (append_server_config "https://aether.example" "stolen-token" "node-hardlink" "off" "") 2>/dev/null; then
|
|
fail_test "hard-linked config was accepted"
|
|
fi
|
|
[[ "$(cat "${hardlink_victim}")" == 'victim = true' ]] || fail_test "hard-linked config victim was modified"
|
|
|
|
grep -Fq 'Get-Content -LiteralPath' "${POWERSHELL_INSTALLER}" || fail_test "PowerShell reads are not literal-path safe"
|
|
grep -Fq '[IO.File]::Replace' "${POWERSHELL_INSTALLER}" || fail_test "PowerShell config replacement is not atomic"
|
|
grep -Fq 'FileAttributes]::ReparsePoint' "${POWERSHELL_INSTALLER}" || fail_test "PowerShell reparse-point guard is missing"
|
|
grep -Fq 'Assert-NoReparsePointAncestors' "${POWERSHELL_INSTALLER}" \
|
|
|| fail_test "PowerShell ancestor reparse-point guard is missing"
|
|
grep -Fq "LinkType -eq 'HardLink'" "${POWERSHELL_INSTALLER}" || fail_test "PowerShell hard-link guard is missing"
|
|
grep -Fq 'AllowAutoRedirect = $false' "${POWERSHELL_INSTALLER}" \
|
|
|| fail_test "PowerShell automatic redirects are still enabled"
|
|
grep -Fq 'Assert-TrustedGithubUri $CurrentUri' "${POWERSHELL_INSTALLER}" \
|
|
|| fail_test "PowerShell trusted redirect validation is missing"
|
|
if grep -Eq 'Invoke-(WebRequest|RestMethod)' "${POWERSHELL_INSTALLER}"; then
|
|
fail_test "PowerShell installer still uses an automatically redirecting download command"
|
|
fi
|
|
grep -Fq '[IO.File]::Replace($TempBinary, $TargetBinary' "${POWERSHELL_INSTALLER}" \
|
|
|| fail_test "PowerShell binary replacement is not atomic"
|
|
grep -Fq '$ExpectedLines.Count -ne 1' "${POWERSHELL_INSTALLER}" \
|
|
|| fail_test "PowerShell checksum matching does not reject duplicates"
|
|
grep -Fq 'if (-not $ExpectedMatch.Success)' "${POWERSHELL_INSTALLER}" \
|
|
|| fail_test "PowerShell checksum matching does not reject malformed target entries"
|
|
if grep -Fq 'Select-Object -First 1' "${POWERSHELL_INSTALLER}"; then
|
|
fail_test "PowerShell checksum matching still silently accepts duplicate entries"
|
|
fi
|
|
grep -Fq 'Assert-SafeReleaseRepo $Repo' "${POWERSHELL_INSTALLER}" \
|
|
|| fail_test "PowerShell release repository validation is missing"
|
|
grep -Fq 'Assert-SafeTunnelReleaseTag $Tag' "${POWERSHELL_INSTALLER}" \
|
|
|| fail_test "PowerShell release tag validation is missing"
|
|
grep -Fq 'Assert-SafeNodeName $NodeName' "${POWERSHELL_INSTALLER}" \
|
|
|| fail_test "PowerShell node-name validation is missing"
|
|
if grep -Eq 'Add-Content[[:space:]]+-Path' "${POWERSHELL_INSTALLER}"; then
|
|
fail_test "PowerShell config still uses wildcard-aware Add-Content -Path"
|
|
fi
|
|
|
|
echo "PASS: tunnel installer config safety fixtures"
|