Skip to content

Instantly share code, notes, and snippets.

@vxgmichel
Last active May 4, 2026 17:08
Show Gist options
  • Select an option

  • Save vxgmichel/f5e30b571307cf43eb20d0947958b8c4 to your computer and use it in GitHub Desktop.

Select an option

Save vxgmichel/f5e30b571307cf43eb20d0947958b8c4 to your computer and use it in GitHub Desktop.
Test SSH public key authentication with different version of openssh client
#!/bin/bash
set -eu
# Constants and defaults
USER="root"
PASSWORD=""
VERSIONS=("7.2_p2-r5" "7.9_p1-r6" "8.8_p1-r1" "9.9_p2-r0" "10.2_p1-r0")
KEY_TYPES=("rsa" "ed25519")
SSH_OPTIONS="-o StrictHostKeyChecking=no"
print_help() {
cat <<'EOF'
Usage:
test-ssh-public-key-auth.sh <host>
Description:
Runs an SSH public key authentication matrix test with:
- OpenSSH client versions: 7.2_p2-r5, 7.9_p1-r6, 8.8_p1-r1, 9.9_p2-r0, 10.2_p1-r0
- Key types: rsa, ed25519
Requires Docker to be installed.
EOF
}
silent_unless_fail() {
local err
# Run the command passed as arguments, capture stderr, discard stdout
if ! err=$("$@" 2>/dev/stdout >/dev/null); then
echo -e "\b\b\b: ❌\n$err" >&2
return 1
fi
}
status() {
# Rewrite a single terminal status line for step-by-step progress.
printf "\r\033[K$CURRENT_PREFIX %s" "$1"
}
build_prefix() {
local host="$1"
local version="$2"
local key_type="$3"
local version_fixed
local key_type_fixed
C_RESET=$'\e[0m'
C_DIM=$'\e[2m'
C_HOST_LABEL=$'\e[36m'
C_HOST_VALUE=$'\e[1;96m'
C_VER_LABEL=$'\e[33m'
C_VER_VALUE=$'\e[1;93m'
C_KEY_LABEL=$'\e[32m'
C_KEY_VALUE=$'\e[1;92m'
printf -v version_fixed "%-10.10s" "$version"
printf -v key_type_fixed "%-7.7s" "$key_type"
local prefix="${C_DIM}[${C_RESET}"
prefix+="${C_HOST_LABEL}host${C_RESET}:${C_HOST_VALUE}${host}${C_RESET} "
prefix+="${C_DIM}|${C_RESET} "
prefix+="${C_VER_LABEL}ver${C_RESET}:${C_VER_VALUE}${version_fixed}${C_RESET} "
prefix+="${C_DIM}|${C_RESET} "
prefix+="${C_KEY_LABEL}key${C_RESET}:${C_KEY_VALUE}${key_type_fixed}${C_RESET}"
prefix+="${C_DIM}]${C_RESET}"
printf "%s" "$prefix"
}
run_case() {
local version="$1"
local key_type="$2"
local image="sig9/alpine-openssh-client:$version"
local key_name="regression_testing_${version}_${key_type}"
local comment="$(uuidgen)@testing-${version}-${key_type}"
local cleanup="sed -i /$comment\$/d ~/.ssh/authorized_keys"
CURRENT_PREFIX="$(build_prefix "$HOST" "$version" "$key_type")"
status "Pulling Docker image $image..."
if ! silent_unless_fail docker pull "$image"; then
return 1
fi
status "Testing SSH connection to $USER@$HOST using $image"
rm -f "$key_name" "$key_name.pub"
status "Generating SSH key pair..."
if ! silent_unless_fail docker run --rm -v "$(pwd):/data" "$image" -c "cd /data && ssh-keygen -t $key_type -f $key_name -C '$comment' -N ''"; then
rm -f "$key_name" "$key_name.pub"
return 1
fi
status "Copying public key to $USER@$HOST..."
if ! silent_unless_fail docker run --rm -v "$(pwd):/data" "$image" -c "mkdir -p /root/.ssh && sshpass -p '$PASSWORD' ssh-copy-id -i /data/$key_name.pub $SSH_OPTIONS '$USER@$HOST'"; then
rm -f "$key_name" "$key_name.pub"
return 1
fi
status "Verifying SSH connection..."
if ! silent_unless_fail docker run --rm -v "$(pwd):/data" "$image" -c "ssh $SSH_OPTIONS -i /data/$key_name '$USER@$HOST' 'echo hello'"; then
rm -f "$key_name" "$key_name.pub"
return 1
fi
status "SSH connection successful, cleaning up..."
if ! silent_unless_fail docker run --rm -v "$(pwd):/data" "$image" -c "ssh $SSH_OPTIONS -i /data/$key_name '$USER@$HOST' '$cleanup'"; then
rm -f "$key_name" "$key_name.pub"
return 1
fi
rm -f "$key_name" "$key_name.pub"
status "PASS ✅"
printf "\n"
return 0
}
# Parse arguments
if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
print_help
exit 0
fi
if [ "$#" -ne 1 ]; then
echo "Expected exactly one argument: <host>" >&2
print_help
exit 1
fi
HOST="$1"
# Prompt for password
if [ -z "$PASSWORD" ]; then
read -s -p $'Enter \e[1m'"$USER@$HOST"$'\e[0m password: ' PASSWORD
echo ""
fi
# Run the matrix of tests
TOTAL=0
PASSED=0
FAILED=0
for VERSION in "${VERSIONS[@]}"; do
for KEY_TYPE in "${KEY_TYPES[@]}"; do
TOTAL=$((TOTAL + 1))
if run_case "$VERSION" "$KEY_TYPE"; then
PASSED=$((PASSED + 1))
else
FAILED=$((FAILED + 1))
fi
done
done
printf "\e[1mMatrix run complete\e[0m total: %d \e[32mpassed: %d\e[0m \e[31mfailed: %d\e[0m\n" "$TOTAL" "$PASSED" "$FAILED"
if [ "$FAILED" -gt 0 ]; then
exit 1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment