Skip to content
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

Allow multiple RoT versions in the same repository #6586

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

labbott
Copy link
Contributor

@labbott labbott commented Sep 17, 2024

No description provided.

@labbott labbott marked this pull request as draft September 17, 2024 13:23
Currently we require all versions of the RoT and bootloader
for a particular type (sled, psc, switch) to have identical
versions. This is a stricter requirement than what we actually
care about: All images signed with the same key should be the
same version. Relax this requirement for both the RoT and
its bootloader
@labbott
Copy link
Contributor Author

labbott commented Sep 19, 2024

This is a re-application of #5580 which was reverted because it was only a partial fix and #5851 which never actually merged . The final pieces on top of that are some refactoring in update_tracker.rs to actually choose the right archive and some extra steps for bootloaders

@@ -1351,12 +1351,16 @@ impl SpHandler for Handler {
(SpComponent::ROT, b"NAME", _, _) => ROT_NAME,
(SpComponent::ROT, b"VERS", 0, _) => ROT_VERS0,
(SpComponent::ROT, b"VERS", 1, _) => ROT_VERS1,
// gimlet staging/devel hash
(SpComponent::ROT, b"SIGN", _, _) => &"11594bb5548a757e918e6fe056e2ad9e084297c9555417a025d8788eacf55daf".as_bytes(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we need to keep these hashes in sync with upstream changes over time? ("need" here may not be the right word since this is the simulator and not relevant to production, but maybe it could affect a4x2 or other test envs in some way?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what kind of upstream changes you are thinking of. This hash should never change as it's the same one baked into the CMPA at manufacturing time. We could change it to simulate another set of signing keys.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't thinking of anything specific - mostly naivety! Just to confirm my understanding - the only way this changes is if we rotate our root manufacturing key?

@@ -32,7 +32,7 @@ pub enum Event {
/// TUF repo artifacts unpacked by wicketd, and event reports
ArtifactsAndEventReports {
system_version: Option<SemverVersion>,
artifacts: Vec<ArtifactId>,
artifacts: Vec<(ArtifactId, Option<Vec<u8>>)>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the Option<Vec<u8>>? Maybe worth converting this from a tuple to a struct so we can give it a name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The option is the sign vec. You are right that this should be clarified.

// of the bootloader is going to be identical to the RoT.
pub fn rot_sign(&self) -> Option<Vec<u8>> {
match self.rot_active_slot() {
None => return None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny nit - I think we could remove the outer match via

match self.rot_active_slot()? {
    RotSlot::A => ...

@@ -138,6 +138,13 @@ fn version_or_unknown(caboose: Option<&SpComponentCaboose>) -> String {
caboose.map(|c| c.version.as_str()).unwrap_or("UNKNOWN").to_string()
}

fn caboose_sign(caboose: Option<&SpComponentCaboose>) -> Option<Vec<u8>> {
match caboose {
None => None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit - I think I'd make this function take a non-optional &SpComponentCaboose, since we can't do anything useful with None. That would also make it clear from the signature that even from a non-optional caboose, we may or may not have a sign value.

Comment on lines +116 to +118
.entry(known)
.and_modify(|x| x.push((id.version.clone(), s.clone())))
.or_insert(vec![(id.version.clone(), s.clone())]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit - I think this would be equivalent:

Suggested change
.entry(known)
.and_modify(|x| x.push((id.version.clone(), s.clone())))
.or_insert(vec![(id.version.clone(), s.clone())]);
.entry(known)
.or_default()
.push((id.version.clone(), s.clone()));

and not require repeating the tuple.

@@ -21,12 +21,14 @@ use std::collections::BTreeMap;
use std::fmt::Display;
use wicketd_client::types::{ArtifactId, SemverVersion};

type ArtifactVersions = Vec<(SemverVersion, Option<Vec<u8>>)>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a map instead of a vec? Is it okay to have multiple identical versions with potentially-different Option<Vec<u8>> values?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to map the existing behavior of the map of artifact kind to one version to a map of artifact kind to a vec of all possible versions. I think this is the same issue with using a tuple instead of a named struct. I'll see if that makes it more obvious what's going on here.

@@ -1130,7 +1130,9 @@ fn append_caboose(
git_commit,
// Currently `name` is always the same as `board`, so we'll skip it.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment still accurate? I know it's true for production images, but could this bit of code see non-prod builds with different names?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are correct and it could be helpful to confirm this via wicket.

};
let cnt = v.len();
for (vers, sign) in v {
match (sign, component.rot_sign()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the for/match here; it looks like it could return different values depending on the ordering of v, maybe? E.g., if v has two entries, one with a sign and one without, and component.rot_sign() is none, will we either return vers (line 2455) if the "without a sign" is first or UNKNOWN (MISSING SIGN) (line 2461) if the "with a sign" is first?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assumption is that either all entries will have a SIGN or none of them. This should be checked elsewhere or handled/documented better. This is also related to the type you pointed out in the Vec which is very much a theme here and something I need to rework.

let sign = match caboose.sign() {
Ok(sign) => sign,
Err(error) => {
return Err(RepositoryError::ReadHubrisCabooseBoard { id, error });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be

Suggested change
return Err(RepositoryError::ReadHubrisCabooseBoard { id, error });
return Err(RepositoryError::ReadHubrisCabooseSign { id, error });

(or maybe something like ReadHubrisCabooseValue { id, error, key: "sign" })?

available_artifacts,
available_artifacts_version,
//available_artifacts,
//available_artifacts_version,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple leftover dead fields here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants