fleet/orbit/docs/TUF-Update-Guide.md
Lucas Manuel Rodriguez 832b29f8c7
Update go-tuf to v0.5.0 (bis) (#8112)
* Update go-tuf to v0.5.0

This was triggered by the security advisory
[GHSA-3633-5h82-39pq](https://github.com/theupdateframework/go-tuf/security/advisories/GHSA-3633-5h82-39pq).
Fleet's use of go-tuf is not vulnerable to this issue due to not using
key thresholds greater than 1.

There were some API changes that necessitate changing the initialization
code for the TUF client. See
https://github.com/theupdateframework/go-tuf/issues/379 for further
discussion.

* Add changes file

* Update default root metadata

* Add review changes to update-go-tuf branch

* Update tests

* Add more checks to roots output

Co-authored-by: Zach Wasserman <zach@fleetdm.com>
2022-10-07 17:03:39 -03:00

8.5 KiB

TUF Update Guide

This document is a walkthrough guide for:

The roles needed to push new updates are targets, snapshot and timestamp. See Roles and Metadata.

Become a New Fleet Publisher

Security

  • TUF keys for targets, snapshot and timestamp should be stored on a USB stick (used solely for this purpose).
  • The keys are stored encrypted with a passphrase stored in 1Password (on a private vault).

Sync Fleet's TUF repository

The fleetctl updates --path=<SOME_PATH> commands assume keys/, staged/ and repository/ are under <SOME_PATH> (default value for <SOME_PATH> is the current directory ".").

cd /Volumes/FLEET-TUF/repository

cd /Volumes/FLEET-TUF
mkdir -p repository
mkdir -p keys
mkdir -p staged

aws s3 sync s3://fleet-tuf-repo ./repository

Generate targets+snapshot+timestamp keys

All commands shown in this guide are executed from /Volumes/FLEET-TUF:

cd /Volumes/FLEET-TUF
tuf gen-key targets
Enter targets keys passphrase:
Repeat targets keys passphrase:
Generated targets key with ID ae943cb8be8a849b37c66ed46bdd7e905ba3118c0c051a6ee3cd30625855a076
tuf gen-key snapshot
Enter snapshot keys passphrase:
Repeat snapshot keys passphrase:
Generated snapshot key with ID 1a4d9beb826d1ff4e036d757cfcd6e36d0f041e58d25f99ef3a20ae3f8dd71e3
tuf gen-key timestamp
Enter timestamp keys passphrase:
Repeat timestamp keys passphrase:
Generated timestamp key with ID d940df08b59b12c30f95622a05cc40164b78a11dd7d408395ee4f79773331b30

Share staged/root.json with Fleet member with the root role, who will sign with its root key and push to the repository.

Root role signs the staged/root.json

Essentially the following commands are executed to sign the new keys:

  • tuf sign
  • tuf snapshot
  • tuf timestamp
  • tuf commit

Pushing new updates

Following are tested steps to push new targets.

1. Backup current TUF repository

Just in case we break the remote TUF directory, let's do a local backup:

mkdir ~/tuf.fleetctl.com/backup
aws s3 sync s3://fleet-tuf-repo ~/tuf.fleetctl.com/backup

2. Make sure the local repository is up-to-date

aws s3 sync s3://fleet-tuf-repo ./repository

3. Setup Orbit in Linux, Windows, macOS

Install Orbit with the (to be updated) channels in the three supported OSs.

E.g. if we need to push a new version of osqueryd to edge, then generate and install a package with:

fleetctl package ... --osqueryd-channel=edge ...

4. Setup Orbit in one host that points to our repository

This allows us to verify that already running clients will upgrade successfully.

Serve current unmodified repository:

cd repository && python3 -m http.server

Generate packages using the local TUF server (in my case on a macOS host):

fleetctl package --type=pkg --update-url=http://localhost:8000 ...
[...]

Install generated fleet-osquery.pkg.

5. Actually pushing new updates

In this example we are promoting orbit from edge to stable:

./fleetctl-macos updates add --target ./repository/targets/orbit/linux/edge/orbit --platform linux --name orbit --version 1.1.0 -t 1.1 -t 1 -t stable
[...]
./fleetctl-macos updates add --target ./repository/targets/orbit/windows/edge/orbit.exe --platform windows --name orbit --version 1.1.0 -t 1.1 -t 1 -t stable
[...]
./fleetctl-macos updates add --target ./repository/targets/orbit/macos/edge/orbit --platform macos --name orbit --version 1.1.0 -t 1.1 -t 1 -t stable
[...]

--dryrun allows us to verify the upgrade before pushing:

AWS_PROFILE=tuf aws s3 sync ./repository s3://fleet-tuf-repo --dryrun
(dryrun) upload: repository/snapshot.json to s3://fleet-tuf-repo/snapshot.json
(dryrun) upload: repository/targets.json to s3://fleet-tuf-repo/targets.json
(dryrun) upload: repository/targets/orbit/linux/1.1.0/orbit to s3://fleet-tuf-repo/targets/orbit/linux/1.1.0/orbit
(dryrun) upload: repository/targets/orbit/linux/1.1/orbit to s3://fleet-tuf-repo/targets/orbit/linux/1.1/orbit
(dryrun) upload: repository/targets/orbit/linux/1/orbit to s3://fleet-tuf-repo/targets/orbit/linux/1/orbit
(dryrun) upload: repository/targets/orbit/linux/stable/orbit to s3://fleet-tuf-repo/targets/orbit/linux/stable/orbit
(dryrun) upload: repository/targets/orbit/macos/1.1.0/orbit to s3://fleet-tuf-repo/targets/orbit/macos/1.1.0/orbit
(dryrun) upload: repository/targets/orbit/macos/1.1/orbit to s3://fleet-tuf-repo/targets/orbit/macos/1.1/orbit
(dryrun) upload: repository/targets/orbit/macos/1/orbit to s3://fleet-tuf-repo/targets/orbit/macos/1/orbit
(dryrun) upload: repository/targets/orbit/macos/stable/orbit to s3://fleet-tuf-repo/targets/orbit/macos/stable/orbit
(dryrun) upload: repository/targets/orbit/windows/1.1.0/orbit.exe to s3://fleet-tuf-repo/targets/orbit/windows/1.1.0/orbit.exe
(dryrun) upload: repository/targets/orbit/windows/1.1/orbit.exe to s3://fleet-tuf-repo/targets/orbit/windows/1.1/orbit.exe
(dryrun) upload: repository/targets/orbit/windows/1/orbit.exe to s3://fleet-tuf-repo/targets/orbit/windows/1/orbit.exe
(dryrun) upload: repository/targets/orbit/windows/stable/orbit.exe to s3://fleet-tuf-repo/targets/orbit/windows/stable/orbit.exe
(dryrun) upload: repository/timestamp.json to s3://fleet-tuf-repo/timestamp.json

In this other example we are updating osquery's edge channel:

./fleetctl-macos updates add --target /Users/luk/Downloads/tuf-osqueryd/osqueryd.exe --platform windows --name osqueryd --version 5.5.1 -t edge
[...]
./fleetctl-macos updates add --target /Users/luk/Downloads/tuf-osqueryd/osqueryd.app.tar.gz --platform macos-app --name osqueryd --version 5.5.1 -t edge
[...]
./fleetctl-macos updates add --target /Users/luk/Downloads/tuf-osqueryd/osqueryd --platform linux --name osqueryd --version 5.5.1 -t edge
[...]

--dryrun allows us to verify the upgrade before pushing:

aws s3 sync ./repository s3://fleet-tuf-repo --profile tuf --dryrun
(dryrun) upload: repository/snapshot.json to s3://fleet-tuf-repo/snapshot.json
(dryrun) upload: repository/targets.json to s3://fleet-tuf-repo/targets.json
(dryrun) upload: repository/targets/osqueryd/linux/5.5.1/osqueryd to s3://fleet-tuf-repo/targets/osqueryd/linux/5.5.1/osqueryd
(dryrun) upload: repository/targets/osqueryd/linux/edge/osqueryd to s3://fleet-tuf-repo/targets/osqueryd/linux/edge/osqueryd
(dryrun) upload: repository/targets/osqueryd/macos-app/5.5.1/osqueryd.app.tar.gz to s3://fleet-tuf-repo/targets/osqueryd/macos-app/5.5.1/osqueryd.app.tar.gz
(dryrun) upload: repository/targets/osqueryd/macos-app/edge/osqueryd.app.tar.gz to s3://fleet-tuf-repo/targets/osqueryd/macos-app/edge/osqueryd.app.tar.gz
(dryrun) upload: repository/targets/osqueryd/windows/5.5.1/osqueryd.exe to s3://fleet-tuf-repo/targets/osqueryd/windows/5.5.1/osqueryd.exe
(dryrun) upload: repository/targets/osqueryd/windows/edge/osqueryd.exe to s3://fleet-tuf-repo/targets/osqueryd/windows/edge/osqueryd.exe
(dryrun) upload: repository/timestamp.json to s3://fleet-tuf-repo/timestamp.json

6. Verify the already running test host

Verify host enrolled in step (4) upgraded to the new versions successfully.

7. Verify generation of new packages

fleetctl package --type=pkg --update-url=http://localhost:8000 ...
fleetctl package --type=msi --update-url=http://localhost:8000 ...
fleetctl package --type=deb --update-url=http://localhost:8000 ...

8. Push!

Run the same command shown above, but without --dryrun

aws s3 sync ./repository s3://fleet-tuf-repo --profile tuf

9. Final Verification

Now that the repository is pushed, verify that the hosts enrolled in step (3) update as expected.

Issues found

Invalid timestamp.json version

The following issue was solved by resigning the timestamp metadata fleetctl updates timestamp (executed three times to increase the version to 4175)

2022-08-23T13:44:48-03:00 INF update failed error="update metadata: update metadata: tuf: failed to decode timestamp.json: version 4172 is lower than current version 4174"
2022-08-23T13:59:48-03:00 INF update failed error="update metadata: update metadata: tuf: failed to decode timestamp.json: version 4172 is lower than current version 4174"

Notes

  • "Measure thrice cut once": Steps 3, 4, 5 and 6 allows us to verify the repository is in good shape before pushing to Fleet's TUF service.
  • Steps may look different if the upgrade is performed on a Linux or Windows host.