#repository #update #signing-key #tuf #generate #command-line-tool

app tuftool

Utility for creating and signing The Update Framework (TUF) repositories

26 releases

0.12.0 Oct 10, 2024
0.10.3 Mar 15, 2024
0.10.2 Dec 6, 2023
0.10.1 Nov 8, 2023
0.1.0 Nov 9, 2019

#950 in Web programming

Download history 33/week @ 2024-08-07 47/week @ 2024-08-14 56/week @ 2024-08-21 60/week @ 2024-08-28 273/week @ 2024-09-04 234/week @ 2024-09-11 127/week @ 2024-09-18 131/week @ 2024-09-25 107/week @ 2024-10-02 225/week @ 2024-10-09 45/week @ 2024-10-16 20/week @ 2024-10-23 25/week @ 2024-10-30 21/week @ 2024-11-06 23/week @ 2024-11-13 27/week @ 2024-11-20

99 downloads per month

MIT/Apache

490KB
10K SLoC

tuftool is a Rust command-line utility for generating and signing TUF repositories.

Dependencies

Make sure you have the following dependencies present on your system before installing tuftool:

  • OpenSSL: install libssl-dev on Ubuntu or openssl-devel on Fedora.

Installing

To install the latest version of tuftool:

cargo install --force tuftool

By default, cargo installs binaries to ~/.cargo/bin, so you will need this in your path. See the cargo book for more about installing Rust binary crates.

Minimal TUF Repo

The following is an example of how you can create and download a TUF repository using tuftool. First, create a working directory:

export WRK="${HOME}/tuftool-example"
mkdir -p "${WRK}"

Create a root.json and Signing Key

For production you may want to use a service like AWS KMS, but for this example we will create keys locally as files:

# we will store our root.json in $WRK/root
mkdir "${WRK}/root"
# save the path to the root.json we are about to create, we will use it a lot
export ROOT="${WRK}/root/root.json"

# we will store our signing keys in $WRK/keys
mkdir "${WRK}/keys"

# instantiate a new root.json
tuftool root init "${ROOT}"

# set the root file's expiration date
tuftool root expire "${ROOT}" 'in 6 weeks'

# set the signing threshold for each of the standard signing roles. we are saying
# that each of the following roles must have at least 1 valid signature
tuftool root set-threshold "${ROOT}" root 1
tuftool root set-threshold "${ROOT}" snapshot 1
tuftool root set-threshold "${ROOT}" targets 1
tuftool root set-threshold "${ROOT}" timestamp 1

# create an RSA key and store it as a file. this requires openssl on your system
# this command both creates the key and adds it to root.json for the root role
tuftool root gen-rsa-key "${ROOT}" "${WRK}/keys/root.pem" --role root

# for this example we will re-use the same key for the other standard roles
tuftool root add-key "${ROOT}" -k "${WRK}/keys/root.pem" --role snapshot
tuftool root add-key "${ROOT}" -k "${WRK}/keys/root.pem" --role targets
tuftool root add-key "${ROOT}" -k "${WRK}/keys/root.pem" --role timestamp

# sign root.json
tuftool root sign "${ROOT}" -k "${WRK}/keys/root.pem"

Create a new TUF Repo

Now that we have a root.json file, we can create and sign a TUF repository.

# create a directory to hold the targets that we will sign. we call this the
# 'input' directory because these are the targets that we want to put into
# our TUF repo
mkdir -p "${WRK}/input"

# create the targets that we want in our TUF repo
echo "1" > "${WRK}/input/1.txt"
echo "2" > "${WRK}/input/2.txt"

# create a tuf repo!
tuftool create \
  --root "${ROOT}" \
  --key "${WRK}/keys/root.pem" \
  --add-targets "${WRK}/input" \
  --targets-expires 'in 3 weeks' \
  --targets-version 1 \
  --snapshot-expires 'in 3 weeks' \
  --snapshot-version 1 \
  --timestamp-expires 'in 1 week' \
  --timestamp-version 1 \
  --outdir "${WRK}/tuf-repo"

# you can see our signed repository's metadata here:
ls "${WRK}/tuf-repo/metadata"
# and you can see our signed repository's targets here:
ls "${WRK}/tuf-repo/targets"

### Update TUF Repo

# Change one of the target files
echo "1.1" > "${WRK}/input/1.txt"

# update tuf repo!
tuftool update \
   --root "${ROOT}" \
   --key "${WRK}/keys/root.pem" \
   --add-targets  "${WRK}/input" \
   --targets-expires 'in 3 weeks' \
   --targets-version 2 \
   --snapshot-expires 'in 3 weeks' \
   --snapshot-version 2 \
   --timestamp-expires 'in 1 week' \
   --timestamp-version 2 \
   --outdir "${WRK}/tuf-repo" \
   --metadata-url file:///$WRK/tuf-repo/metadata

Download TUF Repo

Now that we have created TUF repo, we can inspect it using download command. Download command is usually used to download a remote repo using HTTP/S url, but for this example we will use a file based url to download from local repo.

# download tuf repo
tuftool download \
   --root "${ROOT}" \
   -t "file://${WRK}/tuf-repo/targets" \
   -m "file://${WRK}/tuf-repo/metadata" \
   "${WRK}/tuf-downlaod"

HTTP Proxy Support

tuftool respects the HTTPS_PROXY and NO_PROXY environment variables.

Container

You can build a simple container image to avoid needing to install the Rust toolchain and dependencies or your local machine.

To build the image use Docker or Finch (same argument syntax, just replace docker for finch):

docker build -t tuftool .

To use tuftool, mount the host working directory to /share.

For example, to mount the current directory for download you would do something like:

docker run -it -v $(pwd):/share tuftool download "/share/some_directory" ...

Testing

Unit tests are run in the usual manner: cargo test. Integration tests require working AWS credentials and are disabled by default behind a feature named integ. To run all tests, including integration tests: cargo test --features 'integ' or AWS_PROFILE=test-profile cargo test --features 'integ' with specific profile.

Dependencies

~124MB
~3M SLoC