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

Add script to generate metadata for use in compatibility testing. #237

Merged
merged 3 commits into from
Dec 2, 2019

Conversation

alpearce
Copy link
Contributor

(Also check in generated metadata.)

We want to be explicit about making changes to rust-tuf that change the metadata it generates. go-tuf accomplishes this by containing checked-in keys and metadata generated by go-tuf and, in a unit test, asserts that it produces byte-for-byte equivalent metadata. That way, changes to the library that change generated metadata must include corresponding changes to the checked-in metadata to indicate the change in behavior.

This patch includes the metadata generator and the first set of generated metadata. It uses the same keys as the go-tuf generator so that this metadata can also be used for comparison across implementations.

Feel free to go wild on the review; this is the biggest hunk of Rust I've written and I'd appreciate a lot of comments.

Copy link
Collaborator

@erickt erickt left a comment

Choose a reason for hiding this comment

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

A few things other things:

use tuf::repository::{FileSystemRepository, FileSystemRepositoryBuilder, Repository};

// TODO parametrize this better/find it within the build?
const KEYS_PATH: &str = "./keys.json";
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should be okay for now. I've been thinking about re-laying out the directory structure, so we could handle improving discovery of the keys.json file then.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ack.

.join((step - 1).to_string())
.join("repository");
let dst = Path::new(dir).join(step.to_string());
Command::new("cp")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you use /bin/cp, just to make sure we don't pick up any old cp executable in the current directory? It should be okay if this only is runnable on a posix-y system, since this is a test script.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

keys
}

fn copy_repo(dir: &str, step: u8) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Generally speaking I'd prefer this call some rust function to copy the directories, since we might not guarantee that cp is available. Eventually I'd like to turn this into a test library, so that we can add a test that will complain if we accidentally change the metadata format without regenerating the test metadata, like we're doing in go-tuf.

Unfortunately, I'm guessing you discovered there's no standard library way for copying directories. We might be able to pull in a crate for this (fs_extra seems popular, but we need to check out it's quality), but for now I say we punt for now and solve this later for when we create this identity test.

So in short, could you add a // TODO replace this with pure rust library so it's portable across OSes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added TODO.

}

// adds a target and updates the non-root metadata files.
async fn add_target(
Copy link
Collaborator

Choose a reason for hiding this comment

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

More evidence we need a helper library for generating metadata.

Copy link
Contributor

Choose a reason for hiding this comment

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

@alpearce is it ok for you if I attempt at the library part or is it something you would like to do?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fine with me!


async fn generate_repos(dir: &str, consistent_snapshot: bool) -> tuf::Result<()> {
// Create initial repo.
// TODO: @erickt, this impl is very tied to the json keys file. Do we need it to be more flexible?
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should be fine for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ack.

.unwrap();
copy_repo(dir, i);

let root_signer: Option<PrivateKey> = match r {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: I think you can leave off Option<PrivateKey>.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@alpearce
Copy link
Contributor Author

Updated:

  • @erickt's comments
  • use a constant expiration so metadata will be static
  • regenerate metadata with the above

@heartsucker
Copy link
Contributor

Nice! We should fix #238 before merging this one otherwise reviews are going to be impossible.

@alpearce
Copy link
Contributor Author

Borrowed the "linkify-metadata" script from go-tuf and regenerated symlinked metadata.

This adds an interchange called `JsonPretty`, which makes it easier for
humans to review metadata changes. It is identical to
`tuf::interchange::Json`, except for the implementation of `to_writer`.
Instead of writing out the canonical form, it writes out a pretty printed
form of the data.

In addition, it changes `SnapshotMetadataBuilder::insert_metadata_with_path`
and `TimestampMetadataBuilder::from_snapshot` to use `D::to_writer`. This
makes sure that the hash of these metadata files are computed from the
format written to disk, instead of the canonical format.
@erickt
Copy link
Collaborator

erickt commented Nov 27, 2019

A couple more things:

  • I uploaded a pretty printing interchange in Add a json pretty printing interchange #241, could you rebase your patch on top of this one and use it to regenerate the metadata? While you do that, can you squash all the patches together, then factor out the metadata into it's own patch? That should make it easier to review the metadata generation script from the actual metadata.
  • I used your PR to test out that JsonPretty worked (thanks!) I was able to successfully parse step 0, but I ran into a bug in step 1. It is missing the 0 target. Instead, it should look like this.
  • You don't need to do this now, but it'd be nice if we could migrate this script into a separate independent cargo toml. I'd be fine if you want us to do this in a future PR though to get this landed.

@alpearce
Copy link
Contributor Author

Prettified, squashed, separated metadata, fixed bug, added TODO in Cargo.toml.

@erickt erickt merged commit de06c66 into theupdateframework:develop Dec 2, 2019
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.

4 participants