Skip to content

Commit 238048b

Browse files
authored
Fix E2E log collection SSH identity selection (#223)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 3b1da6d commit 238048b

3 files changed

Lines changed: 61 additions & 9 deletions

File tree

hack/e2e/lib/common.sh

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,40 @@ load_config() {
206206
log_info " Skip Cleanup: ${E2E_SKIP_CLEANUP}"
207207
}
208208

209+
# Configure ssh/scp to use the private key matching the VM public key.
210+
configure_ssh_identity() {
211+
if [[ "${E2E_SSH_OPTS}" =~ (^|[[:space:]])-i || "${E2E_SSH_OPTS}" == *"IdentityFile"* ]]; then
212+
return 0
213+
fi
214+
215+
local key_file="${E2E_SSH_PRIVATE_KEY_FILE:-}"
216+
217+
# E2E_SSH_KEY_FILE is the public key passed to Azure VM provisioning.
218+
if [[ -z "${key_file}" && -n "${E2E_SSH_KEY_FILE:-}" && "${E2E_SSH_KEY_FILE}" == *.pub ]]; then
219+
key_file="${E2E_SSH_KEY_FILE%.pub}"
220+
fi
221+
222+
if [[ -z "${key_file}" && -f "${E2E_WORK_DIR}/e2e_ssh_key" ]]; then
223+
key_file="${E2E_WORK_DIR}/e2e_ssh_key"
224+
fi
225+
226+
if [[ -z "${key_file}" ]]; then
227+
local candidate
228+
# DSA keys are intentionally omitted because modern OpenSSH disables them.
229+
for candidate in "${HOME}/.ssh/id_ed25519" "${HOME}/.ssh/id_rsa" "${HOME}/.ssh/id_ecdsa"; do
230+
if [[ -f "${candidate}" && -f "${candidate}.pub" ]]; then
231+
key_file="${candidate}"
232+
break
233+
fi
234+
done
235+
fi
236+
237+
if [[ -n "${key_file}" && -f "${key_file}" ]]; then
238+
export E2E_SSH_IDENTITY_FILE="${key_file}"
239+
log_debug "Using SSH identity file: ${key_file}"
240+
fi
241+
}
242+
209243
# ---------------------------------------------------------------------------
210244
# Work directory & state management
211245
# ---------------------------------------------------------------------------
@@ -253,6 +287,22 @@ state_dump() {
253287
# ---------------------------------------------------------------------------
254288
# SSH helpers
255289
# ---------------------------------------------------------------------------
290+
_build_ssh_opts() {
291+
local -n out_opts="$1"
292+
# E2E_SSH_OPTS is split on shell IFS whitespace; an unset or empty value
293+
# produces no extra options. Identity-file paths are carried separately in
294+
# E2E_SSH_IDENTITY_FILE so spaces are preserved there.
295+
if [[ "${E2E_SSH_OPTS:-}" == *"'"* || "${E2E_SSH_OPTS:-}" == *'"'* || "${E2E_SSH_OPTS:-}" == *"\\"* ]]; then
296+
log_error "E2E_SSH_OPTS must be an unquoted whitespace-delimited option list"
297+
return 1
298+
fi
299+
read -r -a out_opts <<< "${E2E_SSH_OPTS:-}"
300+
301+
if [[ -n "${E2E_SSH_IDENTITY_FILE:-}" ]]; then
302+
out_opts=(-i "${E2E_SSH_IDENTITY_FILE}" -o IdentitiesOnly=yes "${out_opts[@]}")
303+
fi
304+
}
305+
256306
# Wait for SSH to become available on a host
257307
wait_for_ssh() {
258308
local host="$1"
@@ -261,8 +311,9 @@ wait_for_ssh() {
261311

262312
log_info "Waiting for SSH on ${host} (timeout: ${timeout}s)..."
263313
while [[ "${elapsed}" -lt "${timeout}" ]]; do
264-
# shellcheck disable=SC2086
265-
if ssh ${E2E_SSH_OPTS} "${E2E_SSH_USER}@${host}" "echo ready" &>/dev/null; then
314+
local -a ssh_opts
315+
_build_ssh_opts ssh_opts
316+
if ssh "${ssh_opts[@]}" "${E2E_SSH_USER}@${host}" "echo ready" &>/dev/null; then
266317
log_success "SSH ready on ${host} (${elapsed}s)"
267318
return 0
268319
fi
@@ -277,15 +328,17 @@ wait_for_ssh() {
277328
# Execute a command on a remote host via SSH
278329
remote_exec() {
279330
local host="$1"; shift
280-
# shellcheck disable=SC2086
281-
ssh ${E2E_SSH_OPTS} "${E2E_SSH_USER}@${host}" "$@"
331+
local -a ssh_opts
332+
_build_ssh_opts ssh_opts
333+
ssh "${ssh_opts[@]}" "${E2E_SSH_USER}@${host}" "$@"
282334
}
283335

284336
# Copy files to a remote host
285337
remote_copy() {
286338
local src="$1" host="$2" dest="$3"
287-
# shellcheck disable=SC2086
288-
scp ${E2E_SSH_OPTS} "${src}" "${E2E_SSH_USER}@${host}:${dest}"
339+
local -a ssh_opts
340+
_build_ssh_opts ssh_opts
341+
scp "${ssh_opts[@]}" "${src}" "${E2E_SSH_USER}@${host}:${dest}"
289342
}
290343

291344
# ---------------------------------------------------------------------------

hack/e2e/lib/infra.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,7 @@ infra_deploy() {
7272
# Resolve SSH key
7373
local ssh_key
7474
ssh_key="$(_resolve_ssh_key)"
75-
if [[ -f "${E2E_WORK_DIR}/e2e_ssh_key" && "${ssh_key}" == "$(cat "${E2E_WORK_DIR}/e2e_ssh_key.pub")" ]]; then
76-
export E2E_SSH_OPTS="-i ${E2E_WORK_DIR}/e2e_ssh_key -o IdentitiesOnly=yes ${E2E_SSH_OPTS}"
77-
fi
75+
configure_ssh_identity
7876

7977
# Build tags
8078
local run_id="${GITHUB_RUN_ID:-local-$(date +%s)}"

hack/e2e/run.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ main() {
230230
check_prerequisites
231231
load_config
232232
init_work_dir
233+
configure_ssh_identity
233234

234235
trap 'gha_end_group' EXIT
235236

0 commit comments

Comments
 (0)