-
Notifications
You must be signed in to change notification settings - Fork 594
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tests: add spread test for passphrase support #14867
base: fde-manager-features
Are you sure you want to change the base?
tests: add spread test for passphrase support #14867
Conversation
Run nested tests to make sure nothing else broke. |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## fde-manager-features #14867 +/- ##
========================================================
- Coverage 78.20% 78.19% -0.01%
========================================================
Files 1171 1171
Lines 155885 155847 -38
========================================================
- Hits 121903 121869 -34
- Misses 26450 26453 +3
+ Partials 7532 7525 -7
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
# Open port 7777 on the host so that failures in the nested VM (e.g. to | ||
# create users) can be debugged interactively via | ||
# "telnet localhost 7777". Also keeps the logs | ||
# | ||
# XXX: should serial just be logged to stdout so that we just need | ||
# to "journalctl -u $NESTED_VM" to see what is going on ? | ||
if "$QEMU" -version | grep '2\.5'; then | ||
if [ -z "$EXPECT_PASSPHRASE" ]; then | ||
echo "internal error: NESTED_EXPECT_PASSPHRASE is set and qemu doesn't support chardev over socket" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you remember which systems this old version appears on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently it is xenial https://launchpad.net/ubuntu/xenial/+source/qemu.
local expect_passphrase=${3:-} | ||
local log_file=${4:-} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$3
and $4
should be defined if we expect $5
to be defined also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But they are optional, similar to --wait
and --attempts
, no? I might be confused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aah I missed this is snapd-testing-tools, so the changes to this file should go to this repo https://github.com/snapcore/snapd-testing-tools and once they land we sync them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created a PR canonical/snapd-testing-tools#56, but now that I think about it since this is a one off, then maybe I should be entering the passphrase in the test script itself, not as a part of remote.wait-for
, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UPDATE: I changed the test to do the waiting for the passphrase prompt inline, and reverted the changes to remote.wait-for.
echo "remote.wait-for --expect-passphrase without passing an existing --log-file" | ||
return 1 | ||
fi | ||
while [ "$attempts" -ge 0 ]; do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for loop maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The attempt was to be consistent with the loop below, I will update both to be a for loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it seems that all remote.wait-for
helpers use while
, maybe this can be refactored in a followup PR so the script is consistent.
# Wait for passphrase prompt from serial log file. | ||
if MATCH "Please enter the passphrase" < ${log_file}; then | ||
# Enter passphrase to continue boot. | ||
echo "$expect_passphrase" | netcat -N localhost 7777 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we use bash, maybe we can use /dev/tcp/localhost/7777
instead of relying on an external tool that has lots of forks and different command lines.
Or even better, switch that to a unix socket.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd check how far back support for tcp sockets in bash goes, so that we're not surprised by some old version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was not able to get it working with tcp sockets, even locally. I couldn't get qemu to understand that connection is closed and interpret a \n
or \r
to enter the passphrase.
muinstaller_args="-label $label -device $install_disk -rootfs-creator /snap/muinstaller/current/bin/mk-classic-rootfs.sh" | ||
if [ -n "$passphrase" ]; then | ||
muinstaller_args="$muinstaller_args --passphrase $passphrase" | ||
fi | ||
if [ -n "$extra_muinstaller_args" ]; then | ||
muinstaller_args="$muinstaller_args $extra_muinstaller_args" | ||
fi | ||
remote.exec "sudo muinstaller $muinstaller_args" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we could get rid of this big string pass as parameter to remote.exec
and use lists instead.
@@ -19,6 +19,8 @@ run_muinstaller() { | |||
local kernel_assertion="${6}" | |||
local label="${7}" | |||
local disk="${8}" | |||
local passphrase="${9}" | |||
local extra_muinstaller_args="${10}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we just shift
then take the whole "$@"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually there's something fishy about existing code, store_dir
is optional? fortunately there do not seem to be any calls to run_muinstalled that omit store_dir in arguments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bboozzoo good point about store_dir
, I was concerned at first, but turns out that passing args as ${arg}
passes them even if they are empty, so order is preserved.
echo "This test needs test keys to be trusted" | ||
exit | ||
fi | ||
apt install dosfstools kpartx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment about what uses those.
Because specially I am not fan of kpartx, and I would like to know if we can just remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you move dosfstools to the prepare section of tests/nested/manual in spread.yaml? FWIW, those should already be present anyway, so I'm not sure why we need to install them explicitly, perhaps it works without the package too?
As for kpartx it's likely some legacy thing that's incorrectly perpetuated, the prepare sections of tests/nested in spread.yaml list it, but AFAIK we do not need it, neither does ubuntu-image, so if possible we could use it as an opportunity to remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kpartx is used inside tests/lib/tools/setup_nested_hybrid_system.sh
, also fatlabel
which is provided by the dosfstools
package is also used inside tests/lib/tools/setup_nested_hybrid_system.sh
.
I will try to move them up into prepare of tests/nested/manual
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
turns out kpartx is already installed in nested prepare for all variants
remote.exec "sudo apt install -y update-notifier-common" | ||
# Initial reseal count. | ||
remote.exec sudo cat /var/lib/snapd/device/fde/boot-chains > boot-chains-before.json |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we will need to remove this file at some point. I would prefer if we stop adding tests that rely on it.
This file is mostly used to cache and avoid recomputing input for the pcr profiles. But since we have a FDE state now, we will be able to looking into ditching it. So please, do not use that.
You could query the state and look if the pcr profile changed maybe instead.
# Check that on an already provisioned system the API will give a | ||
# sensible reason why the system cannot be installed without further | ||
# action. | ||
remote.exec "sudo snap debug api /v2/systems/classic" > system | ||
gojq '.result."storage-encryption".support' < system | MATCH "unavailable" | ||
gojq '.result."storage-encryption"."unavailable-reason"' < system | MATCH "not encrypting device storage as checking TPM gave: the TPM is in DA lockout mode" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit confusing. I am not sure why we test this here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied that check from muinstaller-real. you are right, it is not relevant here.
# Check that a reboot notification was setup. | ||
remote.exec test -f /run/reboot-required | ||
remote.exec cat /run/reboot-required.pkgs | MATCH "snap:${snap_name}" | ||
# Check that no reboot has been scheduled, then force a reboot | ||
remote.exec not test -f /run/systemd/shutdown/scheduled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is not this going to change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure I fully understand
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I think this could be removed
printf "Test installing snap from file %s\n" "$snap_filename" | ||
remote.push "$snap_filename" | ||
# install will exit when waiting for the reboot | ||
remote.exec sudo snap install --dangerous "$snap_filename" | MATCH "Task set to wait until a system restart allows to continue" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not this one depend on reboot_action
?
5802840
to
5ec2e43
Compare
-rootfs-creator /snap/muinstaller/current/bin/mk-classic-rootfs.sh" | ||
muinstaller_args="-label $label -device $install_disk -rootfs-creator /snap/muinstaller/current/bin/mk-classic-rootfs.sh" | ||
if [ -n "$passphrase" ]; then | ||
muinstaller_args="$muinstaller_args --passphrase $passphrase" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
muinstaller_args="$muinstaller_args --passphrase $passphrase" | |
muinstaller_args="$muinstaller_args --passphrase "$passphrase"" |
just out of curiosity, I'd check whether a passphrase containing a space character is correctly handled.
@@ -19,6 +19,8 @@ run_muinstaller() { | |||
local kernel_assertion="${6}" | |||
local label="${7}" | |||
local disk="${8}" | |||
local passphrase="${9}" | |||
local extra_muinstaller_args="${10}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually there's something fishy about existing code, store_dir
is optional? fortunately there do not seem to be any calls to run_muinstalled that omit store_dir in arguments
echo "This test needs test keys to be trusted" | ||
exit | ||
fi | ||
apt install dosfstools kpartx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you move dosfstools to the prepare section of tests/nested/manual in spread.yaml? FWIW, those should already be present anyway, so I'm not sure why we need to install them explicitly, perhaps it works without the package too?
As for kpartx it's likely some legacy thing that's incorrectly perpetuated, the prepare sections of tests/nested in spread.yaml list it, but AFAIK we do not need it, neither does ubuntu-image, so if possible we could use it as an opportunity to remove it.
71c83de
to
afce113
Compare
6d526ac
to
c26ec1b
Compare
c08093a
to
6a9cd05
Compare
7005c64
to
25f9119
Compare
This spread test is disabled currently since the corrosponding passphrase support didn't land yet. Signed-off-by: Zeyad Gouda <[email protected]>
Signed-off-by: Zeyad Gouda <[email protected]>
Signed-off-by: Zeyad Gouda <[email protected]>
Signed-off-by: Zeyad Gouda <[email protected]>
Signed-off-by: Zeyad Gouda <[email protected]>
Signed-off-by: Zeyad Gouda <[email protected]>
using tcp socket file caused the VM to keep waiting Signed-off-by: Zeyad Gouda <[email protected]>
6a9cd05
to
1d1a2df
Compare
Rebased on top of latest fde branch |
Tue Feb 4 19:02:03 UTC 2025 Failures:Preparing:
Executing:
Restoring:
|
Replacing myself here with Alfonso that should know about the muinstaller etc |
local expect_passphrase=${3:-} | ||
local log_file=${4:-} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local expect_passphrase=${3:-} | |
local log_file=${4:-} | |
local expect_passphrase=${3} | |
local log_file=${4} |
(and the same for the 2 preceding lines)
I think I'd drop the undefined expansion and simply let it fail to catch the bugs in how this function is called. We're expecting all positional arguments being passed to this function anyway
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reverted the changes to remote.wait-for in favor of doing the waiting for the passphrase prompt inline in the test script directly. No need to change testing tools for a one off case like passphrases.
# Wait for passphrase prompt from serial log file. | ||
if MATCH "Please enter the passphrase" < ${log_file}; then | ||
# Enter passphrase to continue boot. | ||
echo "$expect_passphrase" | netcat -N localhost 7777 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd check how far back support for tcp sockets in bash goes, so that we're not surprised by some old version
Signed-off-by: Zeyad Gouda <[email protected]>
1d19d37
to
685389a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, some small comments. I am not sure if we should merge this until the feature branch is merged though.
"architecture": "amd64", | ||
"timestamp": "2024-04-09T22:00:00+00:00", | ||
"grade": "dangerous", | ||
"base": "core22", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably want core24 here. Or is it maybe necessary because the kernel in classic-24.10/edge
uses core24 incorrectly?
@@ -1204,13 +1204,20 @@ nested_start_core_vm_unit() { | |||
PARAM_RTC="${NESTED_PARAM_RTC:-}" | |||
PARAM_EXTRA="${NESTED_PARAM_EXTRA:-}" | |||
|
|||
local EXPECT_PASSPHRASE | |||
EXPECT_PASSPHRASE=${NESTED_EXPECT_PASSPHRASE:-} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that the practice is insted to have a statement like : "${NESTED_EXPECT_PASSPHRASE:=}"
at the bgining of nested.sh
muinstaller_args+=("-label $label") | ||
muinstaller_args+=("-device $install_disk") | ||
muinstaller_args+=("-rootfs-creator /home/user1/mk-classic-rootfs-wrapper.sh") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't each argument be separate? Like args+=("-label" "$label")
, etc. I think that in the end is not relevant as remote.exec
somewhat is possibly splitting arguments, but still.
@@ -196,7 +204,11 @@ EOF | |||
fi | |||
|
|||
# Start installed image | |||
tests.nested create-vm core --keep-firmware-state | |||
if [ -n "$passphrase" ]; then | |||
tests.nested create-vm core --keep-firmware-state --expect-passphrase "$passphrase" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: maybe better just --passphrase
? expect-passphrase sounds a bit like a boolean.
@@ -338,7 +360,7 @@ main() { | |||
|
|||
run_muinstaller "${model_assertion}" "${store_dir}" "${gadget_snap}" \ | |||
"${gadget_assertion}" "${kernel_snap}" "${kernel_assertion}" "${label}" \ | |||
"${disk}" "${kern_mods_comp}" | |||
"${disk}" "${kern_mods_comp}" "${passphrase}" "${extra_muinstaller_args[@]}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way it is initialized, you get only one argument here, ${extra_muinstaller_args[0]}
This PR adds spread tests for passphrase support for hybrid and core24.
Passphrase support has not landed yet, the spread test could be verified against the spike branch if needed.
Hybrid standalone tests:
Core24 smoke test variant (for Core Desktop):
The added tests are currently disabled to be enabled when the corresponding support lands.
An alternative could be to enable them and have them intentionally fail until support lands.