fix(prelaunch): v0.0.19 - correct SSH key count and log key fingerprints - #115
Merged
Conversation
A CVM booting with one injected key logged "total 0 keys". The count came
from `wc -l`, which counts newlines, while `jq -j` writes the value with
no trailing newline — so a one-key file counted as zero. The same missing
newline meant a later append would concatenate onto the previous line and
silently corrupt authorized_keys, and the "more than one line" guard kept
the dedup pass from running for a two-key file.
v0.0.19:
- Write with `jq -r` so the value is newline-terminated.
- Dedup unconditionally, which also drops the blank line an empty key
list leaves behind.
- Count with a pattern that does not depend on the final newline.
- Log the SHA256 fingerprint of every authorized key, in the format
`ssh-keygen -lf` and GitHub use, so a boot log can be matched against
the account's key list without shelling into the CVM.
The guest image has neither ssh-keygen nor a base64 applet — every dstack
0.5.x image builds BusyBox from the same kirkstone defconfig, which ships
base32 only — so openssl performs both the decode and the digest, guarded
by a command -v check. openssl is present in every 0.5.x image via
ca-certificates.
`openssl base64 -d` exits 0 on undecodable input and emits nothing, which
would print the SHA256 of the empty string as a real fingerprint; the
decoded byte count is checked first and such a line prints
"<unreadable key>" instead.
Sample output, verified byte-identical to `ssh-keygen -lf`:
Set root authorized_keys from user preferences, total 2 keys
ssh-ed25519 SHA256:6OKoIHh0+L2URA+iptwZ1EF3NlwXZ6o0BW9/bnoR7ds
ssh-rsa SHA256:LxIr2ZUyQLBZtTcELwmpjnhrYTYL/4ZUhXb2ngIo0RU
Matches the v0.0.19 text shipped in Phala Cloud
(Phala-Network/phala-cloud-monorepo#1995); sha256 of this file is
cec8f68ce6185b912023d886bba20cd06386dd9751af904e6107e758b9d68983, the
canonical hash registered there.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A CVM booting with one injected key logged:
The key was written and SSH worked — the count was wrong. It came from
wc -l, which counts newlines, whilejq -jwrites the value with no trailing newline, so a one-key file counted as zero.The same missing newline carried two more consequences: a later append concatenates onto the previous line and silently corrupts
authorized_keys, and thewc -l> 1 guard kept the dedup pass from running for a two-key file.What changed in v0.0.19
jq -rinstead ofjq -j, so the value is newline-terminated.ssh-keygen -lfand GitHub use, so a boot log can be matched against the account's key list without shelling into the CVM.Both values are byte-identical to
ssh-keygen -lfon the same keys.Guest image constraints
The guest image has neither
ssh-keygennor abase64applet — every dstack 0.5.x image builds BusyBox 1.36.1 from the same pinned kirkstone defconfig, which shipsbase32only. Soopensslperforms both the decode and the digest, guarded by acommand -vcheck.opensslis present in every 0.5.x image via ca-certificates, the same dependency v0.0.18 already relies on foropenssl passwd -6.openssl base64 -dexits 0 on undecodable input and emits nothing, which would print the SHA256 of the empty string as a real fingerprint. The decoded byte count is checked first, and such a line prints<unreadable key>instead.Reading the file uses
while read ... || [[ -n "$key_type" ]]so a file with no final newline does not lose its last line — the same trailing-newline trap this release fixes.Verification
Exercised locally against the committed file with real keys, covering repeat execution (idempotent — no duplicate or concatenated lines on a second boot), an empty key list, a file with no final newline, and an undecodable blob.
bash -nclean.