Commit: Add composefs digest and sig to the commit metadata

If `composefs-apply-sig` is enabled (default no) we add an
ostree.composefs digest to the commit metadata. This can be verified
on deploy.

This is a separate option from the generic `composefs` option which
controls whether composefs is used during deploy. It is separate
because we want to not have to force use of fs-verity, etc during the
build.

If the `composefs-certfile` and `composefs-keyfile` keys in the
ex-integrity group are set, then the commit metadata also gets a
ostree.composefs-sig containing the signature of the composefs file.
This commit is contained in:
Alexander Larsson 2023-05-15 15:18:16 +02:00
parent e2956e2c08
commit 0c3d9894be
3 changed files with 98 additions and 10 deletions

View File

@ -398,14 +398,9 @@ compare_ascii_checksums_for_sorting (gconstpointer a_pp, gconstpointer b_pp)
/*
* Create sizes metadata GVariant and add it to the metadata variant given.
*/
static GVariant *
add_size_index_to_metadata (OstreeRepo *self, GVariant *original_metadata)
static void
add_size_index_to_metadata (OstreeRepo *self, GVariantBuilder *builder)
{
g_autoptr (GVariantBuilder) builder = NULL;
/* original_metadata may be NULL */
builder = ot_util_variant_builder_from_variant (original_metadata, G_VARIANT_TYPE ("a{sv}"));
if (self->object_sizes && g_hash_table_size (self->object_sizes) > 0)
{
GVariantBuilder index_builder;
@ -443,8 +438,6 @@ add_size_index_to_metadata (OstreeRepo *self, GVariant *original_metadata)
/* Clear the object sizes hash table for a subsequent commit. */
g_hash_table_remove_all (self->object_sizes);
}
return g_variant_ref_sink (g_variant_builder_end (builder));
}
static gboolean
@ -2912,6 +2905,23 @@ ostree_repo_write_commit (OstreeRepo *self, const char *parent, const char *subj
out_commit, cancellable, error);
}
static GVariant *
add_auto_metadata (OstreeRepo *self, GVariant *original_metadata, OstreeRepoFile *repo_root,
GCancellable *cancellable, GError **error)
{
g_autoptr (GVariantBuilder) builder = NULL;
/* original_metadata may be NULL */
builder = ot_util_variant_builder_from_variant (original_metadata, G_VARIANT_TYPE ("a{sv}"));
add_size_index_to_metadata (self, builder);
if (!ostree_repo_commit_add_composefs_metadata (self, builder, repo_root, cancellable, error))
return NULL;
return g_variant_ref_sink (g_variant_builder_end (builder));
}
/**
* ostree_repo_write_commit_with_time:
* @self: Repo
@ -2938,7 +2948,10 @@ ostree_repo_write_commit_with_time (OstreeRepo *self, const char *parent, const
OstreeRepoFile *repo_root = OSTREE_REPO_FILE (root);
/* Add sizes information to our metadata object */
g_autoptr (GVariant) new_metadata = add_size_index_to_metadata (self, metadata);
g_autoptr (GVariant) new_metadata
= add_auto_metadata (self, metadata, repo_root, cancellable, error);
if (new_metadata == NULL)
return FALSE;
g_autoptr (GVariant) commit = g_variant_new (
"(@a{sv}@ay@a(say)sst@ay@ay)", new_metadata ? new_metadata : create_empty_gvariant_dict (),

View File

@ -558,3 +558,74 @@ ostree_repo_checkout_composefs (OstreeRepo *self, OstreeComposefsTarget *target,
return FALSE;
#endif
}
#ifdef HAVE_COMPOSEFS
static gboolean
ostree_repo_commit_add_composefs_sig (OstreeRepo *self, GVariantBuilder *builder,
guchar *fsverity_digest, GCancellable *cancellable,
GError **error)
{
g_autofree char *certfile = NULL;
g_autofree char *keyfile = NULL;
g_autoptr (GBytes) sig = NULL;
certfile
= g_key_file_get_string (self->config, _OSTREE_INTEGRITY_SECTION, "composefs-certfile", NULL);
keyfile
= g_key_file_get_string (self->config, _OSTREE_INTEGRITY_SECTION, "composefs-keyfile", NULL);
if (certfile == NULL && keyfile == NULL)
return TRUE;
if (certfile == NULL)
return glnx_throw (error, "Error signing compoosefs: keyfile specified but certfile is not");
if (keyfile == NULL)
return glnx_throw (error, "Error signing compoosefs: certfile specified but keyfile is not");
if (!_ostree_fsverity_sign (certfile, keyfile, fsverity_digest, &sig, cancellable, error))
return FALSE;
g_variant_builder_add (builder, "{sv}", "ostree.composefs-sig", ot_gvariant_new_ay_bytes (sig));
return TRUE;
}
#endif
gboolean
ostree_repo_commit_add_composefs_metadata (OstreeRepo *self, GVariantBuilder *builder,
OstreeRepoFile *repo_root, GCancellable *cancellable,
GError **error)
{
gboolean add_metadata;
if (!ot_keyfile_get_boolean_with_default (self->config, _OSTREE_INTEGRITY_SECTION,
"composefs-add-metadata", FALSE, &add_metadata, error))
return FALSE;
if (add_metadata)
{
#ifdef HAVE_COMPOSEFS
/* Create a composefs image and put in deploy dir as .ostree.cfs */
g_autoptr (OstreeComposefsTarget) target = ostree_composefs_target_new ();
if (!ostree_repo_checkout_composefs (self, target, repo_root, cancellable, error))
return FALSE;
g_autofree guchar *fsverity_digest = NULL;
if (!ostree_composefs_target_write (target, -1, &fsverity_digest, cancellable, error))
return FALSE;
g_variant_builder_add (builder, "{sv}", "ostree.composefs",
ot_gvariant_new_bytearray (fsverity_digest, OSTREE_SHA256_DIGEST_LEN));
if (!ostree_repo_commit_add_composefs_sig (self, builder, fsverity_digest, cancellable,
error))
return FALSE;
#else
return glnx_throw (error, "composefs required, but libostree compiled without support");
#endif
}
return TRUE;
}

View File

@ -465,6 +465,10 @@ gboolean ostree_repo_checkout_composefs (OstreeRepo *self, OstreeComposefsTarget
OstreeRepoFile *source, GCancellable *cancellable,
GError **error);
gboolean ostree_repo_commit_add_composefs_metadata (OstreeRepo *self, GVariantBuilder *builder,
OstreeRepoFile *repo_root,
GCancellable *cancellable, GError **error);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeComposefsTarget, ostree_composefs_target_unref)
G_END_DECLS