tough: Rust implementation of The Update Framework (TUF)
repository·develop·Indexed 42 days ago
https://github.com/awslabs/toughA Rust-based ecosystem for implementing The Update Framework (TUF), featuring a client library for consuming secure updates and the tuftool CLI for repository maintainers to generate and sign metadata. Includes specialized crates such as tough-kms and tough-ssm for AWS-backed key management, and olpc-cjson for OLPC-style canonical JSON serialization.
What's inside tough
- tough is a Rust client designed for interacting with The Update Framework (TUF) repositories. It provides the necessary logic to securely consume TUF-compliant updates.
Overview of the tough project
developThe
toughproject provides tools for interacting with The Update Framework (TUF) repositories. It consists of two primary components:- tough: A Rust client library designed for consuming TUF repositories.
- tuftool: A Rust command-line utility used for the generation and signing of TUF repositories.
Additionally, the project includes specialized crates for key management, such as
tough-kmsandtough-ssm, which implement theKeySourcetrait for AWS services.Use AWS KMS as a key source for TUF repositories
developThetough-kmscrate allows you to use AWS Key Management Service (KMS) as a source for keys used to sign a The Update Framework (TUF) repository. It achieves this by implementing theKeySourcetrait defined in the coretoughRust library. This enables secure, hardware-backed signing operations for TUF metadata using AWS KMS.How delegated targets work in tough
developDelegated targets create a chain of trust from a repository owner to developers by delegating specific paths in a repository to other roles. This creates a cryptographically verified delegation chain where updated targets are guaranteed to be from the developer who signed the metadata.
In the
toughlibrary, there are two primary ways to manage these delegations:RepositoryEditor: Used by users who have access to the standard TUF roles (snapshot.json,timestamp.json,targets.json). It can edit the entire repository, create complete signed metadata, and manage the delegation chain (adding/updating roles).TargetsEditor: Used by delegated roles that do not have access to the standard TUF roles. It is used to edit specific targets metadata. Metadata produced by aTargetsEditoris signed but does not constitute a full repository; it must be loaded into aRepositoryEditorto complete the signed repository structure.
// Conceptual usage of the two editor types // RepositoryEditor (Full access) // TargetsEditor (Delegated access only)Run integration tests with noxious
developTo run the integration tests for the project, you must have
noxiousinstalled. You can trigger the integration test suite by running the following command viamake:make integCreate a new TUF repository
developUse the
tuftool createcommand to generate a signed TUF repository from a directory of target files. You must provide theroot.jsonpath, a signing key, the directory containing targets, and version/expiration metadata fortargets,snapshot, andtimestamproles.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"Use tuftool via Docker container
developTo avoid installing the Rust toolchain, you can build and run
tuftoolusing Docker.- Build the image:
docker build -t tuftool . - Run commands by mounting your host working directory to
/shareinside the container.
Example for downloading to a local directory:
docker run -it -v $(pwd):/share tuftool download "/share/some_directory" ...docker build -t tuftool . docker run -it -v $(pwd):/share tuftool download "/share/some_directory" ...- Build the image:
Download a TUF repository
developUse
tuftool downloadto fetch a repository. While typically used with HTTP/S URLs, it also supports local file URLs. You must specify the paths to thetargetsandmetadatadirectories using the-tand-mflags.tuftool download \ --root "${ROOT}" \ -t "file://${WRK}/tuf-repo/targets" \ -m "file://${WRK}/tuf-repo/metadata" \ "${WRK}/tuf-downlaod"Use AWS SSM as a key source for TUF repositories
developThetough-ssmcrate provides an implementation of theKeySourcetrait for thetoughRust library. This allows you to use AWS Systems Manager (SSM) Parameter Store to store and retrieve the cryptographic keys required to sign a The Update Framework (TUF) repository.Initialize and configure a TUF root.json
developBefore creating a repository, you must initialize a
root.jsonfile, set expiration dates, define signing thresholds for standard roles (root,snapshot,targets,timestamp), and generate/add signing keys.Standard workflow:
tuftool root init <path>: Create the file.tuftool root expire <path> <duration>: Set expiration (e.g., 'in 6 weeks').tuftool root set-threshold <path> <role> <threshold>: Define how many signatures are required for a role.tuftool root gen-rsa-key <path> <key_path> --role <role>: Create a new RSA key and add it to the root file.tuftool root add-key <path> -k <key_path> --role <role>: Add an existing key to a role.tuftool root sign <path> -k <key_path>: Sign theroot.jsonfile.
# Example initialization tuftool root init "${ROOT}" tuftool root expire "${ROOT}" 'in 6 weeks' tuftool root set-threshold "${ROOT}" root 1 tuftool root gen-rsa-key "${ROOT}" "${WRK}/keys/root.pem" --role root tuftool root sign "${ROOT}" -k "${WRK}/keys/root.pem"Add or remove keys from delegated roles using tuftool
developYou can manage which keys are authorized to sign for a delegated role by using the
add-keyandremove-keysubcommands undertuftool delegation.Adding a key
Use
add-keyto authorize a new key for a delegated role. This requires the signing key of the parent role and the path to the new key. After adding the key, you must runtuftool updatefor the parent role to commit the changes to the repository metadata.Removing a key
Use
remove-keyto revoke a specific key from a delegated role. You must provide the--keyidof the key being removed. Like adding a key, this requires a subsequenttuftool updateto finalize the change in the repository.Note: Always follow a delegation change with a
tuftool updatecommand targeting the parent role to ensure the repository metadata is consistent.# Add a key to targets to sign role1 tuftool delegation --signing-role targets add-key \ --key path/to/repo/owner/key \ --new-key path/to/new/role1/key \ --expires in 2 days \ --version 63 \ --delegated-role role1 \ --outdir targets/with/extra/role1/key \ --root path/to/root.json \ --metadata-url path/to/metadata # Update the repository with the new targets metadata tuftool update \ --key path/to/repo/owner/key \ --snapshot-version 74 \ --snapshot-expires in 3 days \ --targets-version 63 \ --targets-expires in 7 days \ --timestamp-version 593 \ --timestamp-expires in 1 day \ --role targets \ --incoming-metadata targets/with/extra/role1/key \ --outdir metadata/with/updated/role1/keys \ --root path/to/root.json \ --metadata-url path/to/metadataRemove a delegated role using tuftool
developTo remove a delegated role from a parent role, use the
tuftool delegation add-keycommand (as shown in the example, this appears to be the mechanism for modifying the delegation structure) or the relevant removal command to strip the delegation. After the delegation is removed, you must runtuftool updatefor the parent role to update the repository metadata.# Remove role1 from targets tuftool delegation --signing-role targets add-key \ --key path/to/repo/owner/key \ --delegated-role role1 \ --expires in 2 days \ --version 63 \ --outdir targets/with/removed/role1/key \ --root path/to/root.json \ --metadata-url path/to/metadata # Update the repository with the new targets metadata tuftool update \ --key path/to/repo/owner/key \ --snapshot-version 74 \ --targets-version 63 \ --targets-expires in 7 days \ --timestamp-version 593 \ --timestamp-expires in 1 day \ --role targets \ --incoming-metadata targets/with/removed/role1/key \ --outdir metadata/with/updated/role1/keys \ --root path/to/root.json \ --metadata-url path/to/metadata