app/deploy: Add --skip-branch-check

In Fedora CoreOS, updates are driven by Zincati and we thus completely
trust the information it gives us. The branch validation rpm-ostree does
is thus not necessary. It's also harmful in the case where the node is
extremely out of date because it may not be able to GPG verify the
commit at the tip of the branch (because the GPG key isn't yet in the
tree).

See: https://github.com/coreos/fedora-coreos-tracker/issues/749
This commit is contained in:
Jonathan Lebon 2021-05-07 17:28:24 -04:00
parent c7bf08789d
commit 7c1072f965
4 changed files with 27 additions and 5 deletions

View File

@ -37,6 +37,7 @@ static gboolean opt_lock_finalization;
static gboolean opt_disallow_downgrade; static gboolean opt_disallow_downgrade;
static gboolean opt_unchanged_exit_77; static gboolean opt_unchanged_exit_77;
static gboolean opt_bypass_driver; static gboolean opt_bypass_driver;
static gboolean opt_skip_branch_check;
static GOptionEntry option_entries[] = { static GOptionEntry option_entries[] = {
{ "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Operate on provided OSNAME", "OSNAME" }, { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Operate on provided OSNAME", "OSNAME" },
@ -48,6 +49,7 @@ static GOptionEntry option_entries[] = {
{ "preview", 0, 0, G_OPTION_ARG_NONE, &opt_preview, "Just preview package differences", NULL }, { "preview", 0, 0, G_OPTION_ARG_NONE, &opt_preview, "Just preview package differences", NULL },
{ "cache-only", 'C', 0, G_OPTION_ARG_NONE, &opt_cache_only, "Do not download latest ostree and RPM data", NULL }, { "cache-only", 'C', 0, G_OPTION_ARG_NONE, &opt_cache_only, "Do not download latest ostree and RPM data", NULL },
{ "download-only", 0, 0, G_OPTION_ARG_NONE, &opt_download_only, "Just download latest ostree and RPM data, don't deploy", NULL }, { "download-only", 0, 0, G_OPTION_ARG_NONE, &opt_download_only, "Just download latest ostree and RPM data, don't deploy", NULL },
{ "skip-branch-check", 0, 0, G_OPTION_ARG_NONE, &opt_skip_branch_check, "Do not check if commit belongs on the same branch", NULL },
{ "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL }, { "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL },
{ "disallow-downgrade", 0, 0, G_OPTION_ARG_NONE, &opt_disallow_downgrade, "Forbid deployment of chronologically older trees", NULL }, { "disallow-downgrade", 0, 0, G_OPTION_ARG_NONE, &opt_disallow_downgrade, "Forbid deployment of chronologically older trees", NULL },
{ "unchanged-exit-77", 0, 0, G_OPTION_ARG_NONE, &opt_unchanged_exit_77, "If no new deployment made, exit 77", NULL }, { "unchanged-exit-77", 0, 0, G_OPTION_ARG_NONE, &opt_unchanged_exit_77, "If no new deployment made, exit 77", NULL },
@ -132,6 +134,7 @@ rpmostree_builtin_deploy (int argc,
g_variant_dict_insert (&dict, "allow-downgrade", "b", !opt_disallow_downgrade); g_variant_dict_insert (&dict, "allow-downgrade", "b", !opt_disallow_downgrade);
g_variant_dict_insert (&dict, "cache-only", "b", opt_cache_only); g_variant_dict_insert (&dict, "cache-only", "b", opt_cache_only);
g_variant_dict_insert (&dict, "download-only", "b", opt_download_only); g_variant_dict_insert (&dict, "download-only", "b", opt_download_only);
g_variant_dict_insert (&dict, "skip-branch-check", "b", opt_skip_branch_check);
g_variant_dict_insert (&dict, "lock-finalization", "b", opt_lock_finalization); g_variant_dict_insert (&dict, "lock-finalization", "b", opt_lock_finalization);
g_variant_dict_insert (&dict, "initiating-command-line", "s", invocation->command_line); g_variant_dict_insert (&dict, "initiating-command-line", "s", invocation->command_line);
if (opt_register_driver) if (opt_register_driver)

View File

@ -314,6 +314,9 @@
"skip-purge" (type 'b') "skip-purge" (type 'b')
Do not purge the old refspec. Only valid if "set-refspec" is Do not purge the old refspec. Only valid if "set-refspec" is
specified. specified.
"skip-branch-check" (type 'b')
When deploying by commit hash (using "set-revision"), do not
check if commit belongs on the same branch.
"no-pull-base" (type 'b') "no-pull-base" (type 'b')
Do not pull a base layer from the remote. Not valid if Do not pull a base layer from the remote. Not valid if
either "set-refspec" or "set-revision" is specified. either "set-refspec" or "set-revision" is specified.

View File

@ -178,6 +178,7 @@ apply_revision_override (RpmostreedTransaction *transaction,
OstreeRepo *repo, OstreeRepo *repo,
OstreeAsyncProgress *progress, OstreeAsyncProgress *progress,
RpmOstreeOrigin *origin, RpmOstreeOrigin *origin,
gboolean skip_branch_check,
const char *revision, const char *revision,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
@ -225,10 +226,13 @@ apply_revision_override (RpmostreedTransaction *transaction,
switch (refspectype) switch (refspectype)
{ {
case RPMOSTREE_REFSPEC_TYPE_OSTREE: case RPMOSTREE_REFSPEC_TYPE_OSTREE:
rpmostree_output_message ("Validating checksum '%s'", checksum); if (!skip_branch_check)
if (!rpmostreed_repo_lookup_checksum (repo, rpmostree_origin_get_refspec (origin), {
checksum, progress, cancellable, error)) rpmostree_output_message ("Validating checksum '%s'", checksum);
return FALSE; if (!rpmostreed_repo_lookup_checksum (repo, rpmostree_origin_get_refspec (origin),
checksum, progress, cancellable, error))
return FALSE;
}
break; break;
case RPMOSTREE_REFSPEC_TYPE_ROJIG: case RPMOSTREE_REFSPEC_TYPE_ROJIG:
/* For now we skip validation here, if there's an error we'll see it later /* For now we skip validation here, if there's an error we'll see it later
@ -358,7 +362,7 @@ package_diff_transaction_execute (RpmostreedTransaction *transaction,
{ {
g_autoptr(OstreeAsyncProgress) progress = ostree_async_progress_new (); g_autoptr(OstreeAsyncProgress) progress = ostree_async_progress_new ();
rpmostreed_transaction_connect_download_progress (transaction, progress); rpmostreed_transaction_connect_download_progress (transaction, progress);
if (!apply_revision_override (transaction, repo, progress, origin, if (!apply_revision_override (transaction, repo, progress, origin, FALSE,
self->revision, cancellable, error)) self->revision, cancellable, error))
return FALSE; return FALSE;
rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction)); rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction));
@ -1116,6 +1120,7 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
g_autoptr(OstreeAsyncProgress) progress = ostree_async_progress_new (); g_autoptr(OstreeAsyncProgress) progress = ostree_async_progress_new ();
rpmostreed_transaction_connect_download_progress (transaction, progress); rpmostreed_transaction_connect_download_progress (transaction, progress);
if (!apply_revision_override (transaction, repo, progress, origin, if (!apply_revision_override (transaction, repo, progress, origin,
deploy_has_bool_option (self, "skip-branch-check"),
self->revision, cancellable, error)) self->revision, cancellable, error))
return FALSE; return FALSE;
rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction)); rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction));

View File

@ -290,6 +290,17 @@ assert_file_has_content status.txt "failed to finalize previous deployment"
assert_file_has_content status.txt "error: opendir" assert_file_has_content status.txt "error: opendir"
echo "ok previous staged failure in status" echo "ok previous staged failure in status"
# check that --skip-branch-check indeeds skips branch checking
csum=$(vm_cmd ostree commit -b otherbranch --tree=ref=vmcheck)
if vm_rpmostree deploy $csum 2>err.txt; then
assert_not_reached "Deployed to commit on different branch"
fi
assert_file_has_content err.txt "Checksum .* not found in .*"
vm_rpmostree cleanup -p
vm_rpmostree deploy $csum --skip-branch-check
vm_rpmostree cleanup -p
echo "ok deploy --skip-branch-check"
# Test `deploy --register-driver` option # Test `deploy --register-driver` option
# Create and start a transient test-driver.service unit to register our fake driver # Create and start a transient test-driver.service unit to register our fake driver
vm_cmd systemd-run --unit=test-driver.service --wait -q \ vm_cmd systemd-run --unit=test-driver.service --wait -q \