Skip to content

Commit fdde8c6

Browse files
committed
ostree-ext: surface libostree signature verification text
Right now when using OSTree remote verification, there's no indication that the OSTree commit was successfully verified. Capture the return string from `OstreeRepo.signature_verify_commit_data` and return it as part of the public `LayeredImageState` object. We could return a more structured signature object here, but this is sufficient for our purposes for now and saves clients from having to regenerate similar looking text. In the `ostree container` CLI, print this verification text. Signed-off-by: Jonathan Lebon <[email protected]>
1 parent f229c20 commit fdde8c6

File tree

3 files changed

+37
-15
lines changed

3 files changed

+37
-15
lines changed

ostree-ext/src/cli.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,9 @@ async fn container_store(
896896
{
897897
eprintln!("{msg}")
898898
}
899+
if let Some(ref text) = import.verify_text {
900+
println!("{text}");
901+
}
899902
println!("Wrote: {} => {}", imgref, import.merge_commit);
900903
Ok(())
901904
}

ostree-ext/src/container/store.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ pub struct LayeredImageState {
127127
pub configuration: ImageConfiguration,
128128
/// Metadata for (cached, previously fetched) updates to the image, if any.
129129
pub cached_update: Option<CachedImageUpdate>,
130+
/// The signature verification text from libostree for the base commit;
131+
/// in the future we should probably instead just proxy a signature object
132+
/// instead, but this is sufficient for now.
133+
pub verify_text: Option<String>,
130134
}
131135

132136
impl LayeredImageState {
@@ -230,6 +234,8 @@ pub struct PreparedImport {
230234
pub ostree_commit_layer: Option<ManifestLayerState>,
231235
/// Any further non-ostree (derived) layers.
232236
pub layers: Vec<ManifestLayerState>,
237+
/// OSTree remote signature verification text, if enabled.
238+
pub verify_text: Option<String>,
233239
}
234240

235241
impl PreparedImport {
@@ -635,6 +641,7 @@ impl ImageImporter {
635641
ostree_layers: component_layers,
636642
ostree_commit_layer: commit_layer,
637643
layers: remaining_layers,
644+
verify_text: None,
638645
};
639646
Ok(Box::new(imp))
640647
}
@@ -804,17 +811,19 @@ impl ImageImporter {
804811
let blob = super::unencapsulate::decompressor(&media_type, blob)?;
805812
let mut archive = tar::Archive::new(blob);
806813
importer.import_commit(&mut archive, Some(cancellable))?;
807-
let commit = importer.finish_import_commit();
814+
let (commit, verify_text) = importer.finish_import_commit();
808815
if write_refs {
809816
repo.transaction_set_ref(None, &target_ref, Some(commit.as_str()));
810817
tracing::debug!("Wrote {} => {}", target_ref, commit);
811818
}
812819
repo.mark_commit_partial(&commit, false)?;
813820
txn.commit(Some(cancellable))?;
814-
Ok::<_, anyhow::Error>(commit)
821+
Ok::<_, anyhow::Error>((commit, verify_text))
815822
});
816-
let commit = super::unencapsulate::join_fetch(import_task, driver).await?;
823+
let (commit, verify_text) =
824+
super::unencapsulate::join_fetch(import_task, driver).await?;
817825
commit_layer.commit = Some(commit);
826+
import.verify_text = verify_text;
818827
if let Some(p) = self.layer_progress.as_ref() {
819828
p.send(ImportProgress::OstreeChunkCompleted(
820829
commit_layer.layer.clone(),
@@ -977,7 +986,7 @@ impl ImageImporter {
977986
.unwrap_or_else(|| chrono::offset::Utc::now().timestamp() as u64);
978987
// Destructure to transfer ownership to thread
979988
let repo = self.repo;
980-
let state = crate::tokio_util::spawn_blocking_cancellable_flatten(
989+
let mut state = crate::tokio_util::spawn_blocking_cancellable_flatten(
981990
move |cancellable| -> Result<Box<LayeredImageState>> {
982991
use rustix::fd::AsRawFd;
983992

@@ -1090,6 +1099,8 @@ impl ImageImporter {
10901099
},
10911100
)
10921101
.await?;
1102+
// We can at least avoid re-verifying the base commit.
1103+
state.verify_text = import.verify_text;
10931104
Ok(state)
10941105
}
10951106
}
@@ -1220,6 +1231,8 @@ pub fn query_image_commit(repo: &ostree::Repo, commit: &str) -> Result<Box<Layer
12201231
manifest,
12211232
configuration,
12221233
cached_update,
1234+
// we can't cross-reference with a remote here
1235+
verify_text: None,
12231236
});
12241237
tracing::debug!("Wrote merge commit {}", state.merge_commit);
12251238
Ok(state)

ostree-ext/src/tar/import.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ enum ImporterMode {
4747
pub(crate) struct Importer {
4848
repo: ostree::Repo,
4949
remote: Option<String>,
50+
verify_text: Option<String>,
5051
// Cache of xattrs, keyed by their content checksum.
5152
xattrs: HashMap<String, glib::Variant>,
5253
// Reusable buffer for xattrs references. It maps a file checksum (.0)
@@ -165,6 +166,7 @@ impl Importer {
165166
Self {
166167
repo: repo.clone(),
167168
remote,
169+
verify_text: None,
168170
buf: vec![0u8; 16384],
169171
xattrs: Default::default(),
170172
next_xattrs: None,
@@ -179,6 +181,7 @@ impl Importer {
179181
Self {
180182
repo: repo.clone(),
181183
remote: None,
184+
verify_text: None,
182185
buf: vec![0u8; 16384],
183186
xattrs: Default::default(),
184187
next_xattrs: None,
@@ -676,14 +679,17 @@ impl Importer {
676679

677680
// Now that we have both the commit and detached metadata in memory, verify that
678681
// the signatures in the detached metadata correctly sign the commit.
679-
self.repo
680-
.signature_verify_commit_data(
681-
remote,
682-
&commit.data_as_bytes(),
683-
&commitmeta.data_as_bytes(),
684-
ostree::RepoVerifyFlags::empty(),
685-
)
686-
.context("Verifying ostree commit in tar stream")?;
682+
self.verify_text = Some(
683+
self.repo
684+
.signature_verify_commit_data(
685+
remote,
686+
&commit.data_as_bytes(),
687+
&commitmeta.data_as_bytes(),
688+
ostree::RepoVerifyFlags::empty(),
689+
)
690+
.context("Verifying ostree commit in tar stream")?
691+
.into(),
692+
);
687693

688694
self.repo.mark_commit_partial(&checksum, true)?;
689695

@@ -738,10 +744,10 @@ impl Importer {
738744
Ok(())
739745
}
740746

741-
pub(crate) fn finish_import_commit(self) -> String {
747+
pub(crate) fn finish_import_commit(self) -> (String, Option<String>) {
742748
tracing::debug!("Import stats: {:?}", self.stats);
743749
match self.data {
744-
ImporterMode::Commit(c) => c.unwrap(),
750+
ImporterMode::Commit(c) => (c.unwrap(), self.verify_text),
745751
ImporterMode::ObjectSet(_) => unreachable!(),
746752
}
747753
}
@@ -821,7 +827,7 @@ pub async fn import_tar(
821827
let txn = repo.auto_transaction(Some(cancellable))?;
822828
let mut importer = Importer::new_for_commit(&repo, options.remote);
823829
importer.import_commit(&mut archive, Some(cancellable))?;
824-
let checksum = importer.finish_import_commit();
830+
let (checksum, _) = importer.finish_import_commit();
825831
txn.commit(Some(cancellable))?;
826832
repo.mark_commit_partial(&checksum, false)?;
827833
Ok::<_, anyhow::Error>(checksum)

0 commit comments

Comments
 (0)