Skip to content

oxidecomputer/tufaceous

Repository files navigation

Tufaceous

Tufaceous is the library and tooling for Oxide update repositories. It is a layer of Oxide-specific tooling on top of tough, a Rust library that implements TUF.

This README is intended to provide a high-level overview of the library and instructions for adding to it. More context can be found in RFD 621.

Repository format

We selected ZIP archives as the primary format for our repositories, despite ZIP's many shortcomings. Because Oxide customers are receiving update repositories and uploading them to their systems, we wanted them to be readable for most users so that they could see what is inside.

The ZIP archive has a top-level repo directory. Inside this directory is a metadata directory, containing the signed TUF metadata, and a targets directory, containing all the targets described by that metadata.

Artifacts

"Artifacts" are our jargon for a file that the Oxide control plane needs in order to perform updates. (All artifacts are "targets", TUF jargon for a file described by the repository metadata, but not all targets are artifacts.)

Artifacts in the repository are described by the artifacts-v2.json. Each artifact has a set of tags that is used by the control plane to decide what to do with the artifact. When creating and using artifacts, these tags are strongly-typed (see KnownArtifactTags in artifact/src/tags.rs), but they are encoded as an arbitrary key-value mapping. This allows us to potentially release a new type of artifact and use it in the same release, once Nexus has been updated.

As a general rule it is not possible to use this tooling to create a repository with arbitrary blobs and artifacts in it. The library is very opinionated about how artifacts are named to keep things usable for the CLI and for users of these repositories.

Tooling

Most of the time you're working with repositories generated by the Omicron release tooling (cargo xtask releng in Omicron). There is also a binary target that is a thin CLI on top of the library, which you can build with cargo build --release --bin tufaceous.

In all commands that read from a repository, use either -r/--trust-roots to provide a list of trust roots to verify signatures against, or --blindly-trust to use the metadata/1.root.json root in the repository as the trust root. If you want to load a repository with an expired signature, use --allow-expired. For convenience you can combine --allow-expired and --blindly-trust with -f/--force-load.

Verify a repository

tufaceous verify will read a repository, print its SHA256 checksum, and verify the metadata and checksums of all the metadata in the repository. It will also run a series of compatibility checks on the repository and warn you of any detected issues.

Unpack a repository

Scripts can use tufaceous list-targets to get a list of targets from the repository, and tufaceous show-target to write a target to stdout.

To unpack an entire repository, use unzip or ZIP tooling provided by your OS.

Build a repository

tufaceous build has two required flags:

  • --output file.zip, which provides the path to write to
  • --system-version 1.0.0, which provides the system version

The arguments are the set of artifacts to add:

  • A measurement corpus is a CoRIM file
  • An OS image is a directory containing cosmo.rom, gimlet.rom, and zfs.img, as produced by helios-build image
  • An RoT, RoT bootloader, or SP image is a Hubris archive (ZIP format)
  • A zone image is a tarball that starts with the oxide.json Omicron brand metadata

When building a repository, an Installinator document is automatically created based on the artifacts in the repository. You can avoid this with --no-installinator-document.

Add/remove artifacts from a repository

Using tufaceous edit you can remove targets from a repository using --remove-targets and add new artifacts using --add-artifacts.

The Installinator document is automatically regenerated based on the artifacts in the final repository. You can avoid this with --no-installinator-document, which will keep an existing Installinator document if there is one.

Adding new artifacts

In order to add a new type of artifact, you will need to make a series of changes to the library:

  • Modify KnownArtifactTags to describe your new artifact
  • Add methods for adding an actual artifact and a fake artifact to RepositoryEditor
  • Add a fake artifact in Input::fake (lib/src/edit/fake.rs)
  • Add code for guessing this type of artifact to Input::guess (lib/src/edit/guess.rs)

As a general rule, Tufaceous artifacts are self-describing. The "guess" code is used by the CLI and generates tags from the artifact to avoid needing an unwieldy set of command line options to describe tags. If your artifact is not self-describing, you can staple a header of some kind to the beginning of the artifact that control plane code knows to strip before using the artifact.

About

Rack update respository generation tool

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages