diff --git a/entrypoint.sh b/entrypoint.sh index 5b9786b..9a1a634 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -38,10 +38,27 @@ trap 'rm -f "$KEY_FILE"' EXIT echo "$INPUT_KEY" > "$KEY_FILE" chmod 600 "$KEY_FILE" +# -P "" so an encrypted key reports a passphrase error instead of hanging on a prompt. +if ! DEPLOY_PUBLIC_KEY="$(ssh-keygen -y -P "" -f "$KEY_FILE" 2>&1)"; then + echo "Error: the 'key' input is not a usable unencrypted OpenSSH private key." >&2 + echo "ssh-keygen: ${DEPLOY_PUBLIC_KEY}" >&2 + exit 1 +fi + +# The public half is not a secret, and printing it is what makes an authentication +# failure diagnosable: it is the exact line that must be in authorized_keys. +echo "Authenticating to ${INPUT_HOST} as ${INPUT_USERNAME} with public key:" +echo " ${DEPLOY_PUBLIC_KEY}" +# The fingerprint is what sshd reports at LogLevel VERBOSE, so printing it here +# lets a rejected key be matched against the target's auth log directly. +echo " fingerprint: $(ssh-keygen -lf "$KEY_FILE" 2>/dev/null || echo unavailable)" + ssh-keyscan -p "$SSH_PORT" -H "$INPUT_HOST" >> "$KNOWN_HOSTS" 2>/dev/null +# BatchMode stops ssh falling back to interactive password auth, which otherwise +# buries a rejected key under two generic "Permission denied" prompts. rsync -avz \ - -e "ssh -i $KEY_FILE -o UserKnownHostsFile=$KNOWN_HOSTS -p $SSH_PORT -o ConnectTimeout=30" \ + -e "ssh -i $KEY_FILE -o IdentitiesOnly=yes -o BatchMode=yes -o UserKnownHostsFile=$KNOWN_HOSTS -p $SSH_PORT -o ConnectTimeout=30" \ $INPUT_ARGS \ "${SOURCE}/" \ "${INPUT_USERNAME}@${INPUT_HOST}:${INPUT_TARGET}/"