Skip to content

Commit c21f5cc

Browse files
committed
dbus: rauc: add manifest_hash und effective_url to UpstreamBundle
The RAUC native polling interface provides more information than just the basic `compatible` and `version` fields. Among these extra informations are the following: - `manifest_hash` By using the `manifest_hash` in the `InstallBundle` call we can (cryptographically) ensure that the exact bundle (content) that the user agreed to install is actually being installed and that no switch has happened in between. - `effective_url` This is the bundle URL after all HTTP redirects have been followed. This is e.g. relevant when a "clever" update server is used that redirects poll requests to specific bundles to e.g. implement staged rollouts or prevents updates from incompatible bundle versions. By using this one can ensure that the bundle URL used matches the `manifest_hash` provided and that the redirects did not change (e.g. because the next step in a staged update was reached) between the last poll and the user accepting an update. The update dialog on the LCD is updated to use this mechanism now, while the web interface will be updated later. Signed-off-by: Leonard Göhrs <l.goehrs@pengutronix.de>
1 parent 0e80ae7 commit c21f5cc

File tree

4 files changed

+35
-7
lines changed

4 files changed

+35
-7
lines changed

openapi.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,10 @@ components:
11411141
type: string
11421142
version:
11431143
type: string,
1144+
manifest_hash:
1145+
type: string,
1146+
effective_url:
1147+
type: string,
11441148
newer_than_installed:
11451149
type: boolean
11461150

src/dbus/rauc.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -553,11 +553,20 @@ impl Rauc {
553553
}
554554
};
555555

556+
let upstream_bundle = match primary.bundle.as_ref() {
557+
Some(us) => us,
558+
None => {
559+
warn!("Got install request with no upstream bundle info available yet");
560+
continue
561+
}
562+
};
563+
556564
let url = match &update_request.url {
557-
None => &primary.url,
565+
None => &upstream_bundle.effective_url,
566+
Some(url) if url == &upstream_bundle.effective_url => &upstream_bundle.effective_url,
558567
Some(url) if url == &primary.url => &primary.url,
559568
Some(_) => {
560-
warn!("Got install request with URL not matching primary channel URL");
569+
warn!("Got install request with URL matching neither channel URL nor effective bundle URL");
561570
continue;
562571
}
563572
};

src/dbus/rauc/update_channels.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ const ONE_DAY: Duration = Duration::from_secs(24 * 60 * 60);
3939
pub struct UpstreamBundle {
4040
pub compatible: String,
4141
pub version: String,
42+
pub manifest_hash: String,
43+
pub effective_url: String,
4244
pub newer_than_installed: bool,
4345
}
4446

@@ -219,12 +221,18 @@ impl Channels {
219221
zvariant_walk_nested_dicts(&poll_status, &["manifest", "update", "compatible"])?;
220222
let version: &zvariant::Str =
221223
zvariant_walk_nested_dicts(&poll_status, &["manifest", "update", "version"])?;
224+
let manifest_hash: &zvariant::Str =
225+
zvariant_walk_nested_dicts(&poll_status, &["manifest", "manifest-hash"])?;
226+
let effective_url: &zvariant::Str =
227+
zvariant_walk_nested_dicts(&poll_status, &["bundle", "effective-url"])?;
222228
let newer_than_installed: &bool =
223229
zvariant_walk_nested_dicts(&poll_status, &["update-available"])?;
224230

225231
if let Some(pb) = self.0.iter().find_map(|ch| ch.bundle.as_ref()) {
226232
if compatible == pb.compatible.as_str()
227233
&& version == pb.version.as_str()
234+
&& manifest_hash == pb.manifest_hash.as_str()
235+
&& effective_url == pb.effective_url.as_str()
228236
&& *newer_than_installed == pb.newer_than_installed
229237
{
230238
return Ok(false);
@@ -237,6 +245,8 @@ impl Channels {
237245
primary.bundle = Some(UpstreamBundle {
238246
compatible: compatible.as_str().into(),
239247
version: version.as_str().into(),
248+
manifest_hash: manifest_hash.as_str().into(),
249+
effective_url: effective_url.as_str().into(),
240250
newer_than_installed: *newer_than_installed,
241251
});
242252
}

src/ui/screens/update_available.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use async_trait::async_trait;
2222
use embedded_graphics::{
2323
mono_font::MonoTextStyle, pixelcolor::BinaryColor, prelude::*, text::Text,
2424
};
25+
use log::error;
2526
use serde::{Deserialize, Serialize};
2627

2728
use super::widgets::*;
@@ -124,12 +125,16 @@ impl Selection {
124125
fn perform(&self, alerts: &Arc<Topic<AlertList>>, install: &Arc<Topic<UpdateRequest>>) {
125126
match self.highlight {
126127
Highlight::Channel(ch) => {
127-
let req = UpdateRequest {
128-
url: Some(self.channels[ch].url.clone()),
129-
manifest_hash: None,
130-
};
128+
if let Some(bundle) = &self.channels[ch].bundle {
129+
let req = UpdateRequest {
130+
url: Some(bundle.effective_url.clone()),
131+
manifest_hash: Some(bundle.manifest_hash.clone()),
132+
};
131133

132-
install.set(req);
134+
install.set(req);
135+
} else {
136+
error!("Update channel is missing upstream bundle information.");
137+
};
133138
}
134139
Highlight::Dismiss => alerts.deassert(SCREEN_TYPE),
135140
}

0 commit comments

Comments
 (0)